Esistono algoritmi O (1 / n)?


335

Esistono algoritmi O (1 / n)?

O qualcos'altro che è inferiore a O (1)?


La maggior parte delle domande presuppone che tu intenda "Esistono algoritmi con una complessità temporale di O (1 / n)?" Supponiamo che sia così? Big-O (e Big-Theta, ecc.) Descrivono funzioni, non algoritmi. (Non conosco alcuna equivalenza tra funzioni e algoritmi.)
jyoungdev

4
Questa è la definizione comunemente intesa di "algoritmo O (X)" nell'informatica: un algoritmo la cui complessità temporale è O (X) (per alcune espressioni X).
David Z,

2
Ho sentito questo limite in caso di efficiente algoritmo di coda di priorità I / O usando Buffer Tree. In un Buffer Tree, ogni operazione prende O (1 / B) I / O; dove B è la dimensione del blocco. E gli I / O totali per n operazioni sono O (n / B.log (base M / B) (n / B)), dove la parte del registro è l'altezza dell'albero buffer.
CODError

Esistono molti algoritmi con probabilità di errore O (1 / n). Ad esempio un filtro bloom con bucket O (n log n).
Thomas Ahle,

Non puoi deporre un uovo più velocemente aggiungendo polli.
Wyck,

Risposte:


310

Questa domanda non è così stupida come potrebbe sembrare. Almeno teoricamente, qualcosa come O (1 / n ) è completamente sensato quando prendiamo la definizione matematica della notazione Big O :

Ora puoi facilmente sostituire g ( x ) con 1 / x ... è ovvio che la definizione sopra vale ancora per qualche f .

Ai fini della stima della crescita runtime asintotica, questo è meno praticabile ... un algoritmo significativo non può essere più veloce man mano che l'input cresce. Certo, puoi costruire un algoritmo arbitrario per soddisfare questo, ad esempio il seguente:

def get_faster(list):
    how_long = (1 / len(list)) * 100000
    sleep(how_long)

Chiaramente, questa funzione impiega meno tempo man mano che le dimensioni dell'input aumentano ... almeno fino a un certo limite, applicato dall'hardware (precisione dei numeri, tempo minimo che sleeppuò attendere, tempo per elaborare argomenti ecc.): Questo limite sarebbe quindi un limite inferiore costante quindi la funzione sopra ha ancora il runtime O (1).

Ma ci sono in realtà algoritmi del mondo reale in cui il tempo di esecuzione può diminuire (almeno parzialmente) quando aumenta la dimensione dell'input. Tuttavia, questi algoritmi non mostreranno un comportamento di runtime inferiore a O (1). Sono comunque interessanti. Ad esempio, prendi il semplicissimo algoritmo di ricerca del testo di Horspool . Qui, il tempo di esecuzione previsto diminuirà con l'aumentare della lunghezza del modello di ricerca (ma l'aumento della lunghezza del pagliaio aumenterà ancora una volta il tempo di esecuzione).


22
'Applicato dall'hardware' si applica anche a una macchina di Turing. Nel caso di O (1 / n) ci sarà sempre una dimensione di input per la quale l'algoritmo non dovrebbe eseguire alcuna operazione. E quindi penso che la complessità temporale O (1 / n) sia davvero impossibile da raggiungere.
Roland Ewald,

28
Mehrdad, non capisci. La notazione O è qualcosa che riguarda il limite (tecnicamente lim sup) come n -> ∞. Il tempo di esecuzione di un algoritmo / programma è il numero di passaggi su una macchina ed è quindi discreto - esiste un limite inferiore diverso da zero sul tempo che un algoritmo può richiedere ("un passo"). Si è possibile che fino a qualche finiti N programmi richiede una serie di misure decrescenti n, ma l'unico modo un algoritmo può essere O (1 / n), o addirittura o (1), è se ci vuole tempo 0 per tutti sufficientemente grande n - che non è possibile.
ShreevatsaR,

28
Non siamo in disaccordo sul fatto che esistano funzioni O (1 / n) (in senso matematico). Ovviamente lo fanno. Ma il calcolo è intrinsecamente discreto. Qualcosa che ha un limite inferiore, come il tempo di esecuzione di un programma - sull'architettura von Neumann o su una macchina di Turing puramente astratta - non può essere O (1 / n). Equivalentemente, qualcosa che è O (1 / n) non può avere un limite inferiore. (La funzione "sleep" deve essere invocata o la variabile "list" deve essere esaminata - oppure il nastro di input deve essere esaminato su una macchina Turing. Quindi il tempo impiegato cambierebbe con n come alcuni ε + 1 / n, che non è O (1 / n))
ShreevatsaR,

16
Se T (0) = ∞, non si ferma. Non esiste "T (0) = ∞, ma si ferma ancora". Inoltre, anche se lavori in R∪ {∞} e definisci T (0) = ∞, e T (n + 1) = T (n) / 2, allora T (n) = ∞ per tutto n. Consentitemi di ripetere: se una funzione a valore discreto è O (1 / n), allora per tutto sufficientemente grande n è 0. [Prova: T (n) = O (1 / n) significa che esiste una costante c tale che per n> N0, T (n) <c (1 / n), che significa che per qualsiasi n> max (N0,1 / c), T (n) <1, che significa T (n) = 0.] Nessuna macchina, reale o astratta, può richiedere 0 tempo: deve guardare l'input. Bene, oltre alla macchina che non fa mai nulla, e per la quale T (n) = 0 per tutto n.
ShreevatsaR,

43
Devi gradire qualsiasi risposta che inizi "Questa domanda non è così stupida come potrebbe sembrare".
Telemaco,

138

Sì.

Esiste esattamente un algoritmo con runtime O (1 / n), l'algoritmo "vuoto".

Per un algoritmo essere O (1 / n) significa che esegue asintoticamente in meno passaggi dell'algoritmo costituito da una singola istruzione. Se viene eseguito in meno passaggi di un passaggio per tutti n> n0, deve consistere esattamente in nessuna istruzione per quelli n. Dal momento che il controllo di 'if n> n0' costa almeno 1 istruzione, non deve consistere in istruzioni per tutte le n.

Riassumendo: l'unico algoritmo che è O (1 / n) è l'algoritmo vuoto, costituito da nessuna istruzione.


2
Quindi, se qualcuno chiedesse qual è la complessità temporale di un algoritmo vuoto, risponderesti con O (1 / n) ??? In qualche modo ne dubito.
Phkahler,

24
Questa è l'unica risposta corretta in questa discussione e (nonostante il mio voto) è a zero voti. Tale è StackOverflow, in cui le risposte "dall'aspetto corretto" sono votate più in alto rispetto a quelle effettivamente corrette.
ShreevatsaR,

5
No, è valutato 0 perché non è corretto. Esprimere un valore di grande Oh in relazione a N quando è indipendente da N non è corretto. In secondo luogo, l'esecuzione di qualsiasi programma, anche solo uno esistente, richiede almeno una quantità costante di tempo, O (1). Anche se non fosse così, sarebbe O (0), non O (1 / n).
kenj0418,

32
Qualsiasi funzione che è O (0) è anche O (1 / n), e anche O (n), anche O (n ^ 2), anche O (2 ^ n). Sospiro, nessuno capisce le definizioni semplici? O () è un limite superiore.
ShreevatsaR,

16
@ kenj0418 Sei riuscito a sbagliarti in ogni singola frase. "Esprimere un valore di grande Oh in relazione a N quando è indipendente da N non è corretto." Una funzione costante è una funzione perfetta. "In secondo luogo, l'esecuzione di qualsiasi programma, anche solo uno esistente, richiede almeno una quantità costante di tempo, O (1)." La definizione di complessità non dice nulla sull'esecuzione effettiva di alcun programma. "sarebbe O (0), non O (1 / n)". Vedi il commento di @ ShreevatsaR.
Alexey Romanov,

25

sharptooth è corretto, O (1) è la migliore prestazione possibile. Tuttavia, non implica una soluzione rapida, ma solo una soluzione a tempo fisso.

Una variante interessante, e forse ciò che viene realmente suggerito, è quali problemi diventano più facili man mano che la popolazione cresce. Mi viene in mente 1, anche se forzato e la risposta ironica:

Due persone in un set hanno lo stesso compleanno? Quando n supera 365, restituisce true. Sebbene per meno di 365, questo è O (n ln n). Forse non è un'ottima risposta poiché il problema non diventa lentamente più semplice ma diventa semplicemente O (1) per n> 365.


7
366. Non dimenticare gli anni bisestili!
Nick Johnson,

1
Hai ragione. Come i computer, occasionalmente sono soggetto ad errori di arrotondamento :-)
Adrian,

10
+1. Esistono numerosi problemi NP completi che subiscono una "transizione di fase" all'aumentare di n, ovvero diventano rapidamente molto più facili o molto più difficili quando si supera un determinato valore di soglia di n. Un esempio è il problema del partizionamento numerico: dato un insieme di n numeri interi non negativi, suddividili in due parti in modo che la somma di ogni parte sia uguale. Questo diventa notevolmente più semplice con un certo valore di soglia di n.
j_random_hacker,

23

Non e possibile. La definizione di Big-O non è maggiore della disuguaglianza:

A(n) = O(B(n))
<=>
exists constants C and n0, C > 0, n0 > 0 such that
for all n > n0, A(n) <= C * B(n)

Quindi B (n) è in realtà il valore massimo, quindi se diminuisce all'aumentare di n la stima non cambierà.


42
Sospetto che questa risposta sia "quella giusta", ma sfortunatamente mi manca l'intelletto per capirla.
Freespace,

12
AFAIK questa condizione non deve essere vera per tutti n, ma per tutti n> n_0 (vale a dire, solo quando la dimensione dell'ingresso raggiunge una soglia specifica).
Roland Ewald,

30
Non vedo come la definizione (anche corretta) contraddica la questione del PO. La definizione vale per funzioni completamente arbitrarie! 1 / n è una funzione completamente sensata per B, e in effetti la tua equazione non lo contraddice (fai solo i calcoli). Quindi no, nonostante molto consenso, questa risposta è in realtà sbagliata . Scusate.
Konrad Rudolph,

10
Sbagliato! Non mi piace il downvoting ma affermi che questo è impossibile quando non c'è un chiaro consenso. In pratica hai ragione, se costruisci una funzione con runtime 1 / n (facile) alla fine colpirà il tempo minimo, rendendolo effettivamente un algoritmo O (1) una volta implementato. Non c'è nulla che impedisca all'algoritmo di essere O (1 / n) su carta.
jheriko,

3
@Jason: Sì, ora che lo dici ... :) @jheriko: Una complessità temporale di O (1 / n) non funziona su carta IMHO. Stiamo caratterizzando la funzione di crescita f (dimensione input) = #ops per una macchina di Turing. Se si ferma per un input di lunghezza n = 1 dopo x passi, allora sceglierò una dimensione di input n >> x, cioè abbastanza grande che, se l'algoritmo è effettivamente in O (1 / n), nessuna operazione dovrebbe essere fatto. Come dovrebbe notarlo anche una macchina Turing (non è consentito leggere una volta dal nastro)?
Roland Ewald,

16

Dal mio precedente apprendimento della notazione O grande, anche se hai bisogno di 1 passo (come controllare una variabile, fare un compito), questo è O (1).

Nota che O (1) è uguale a O (6), perché la "costante" non ha importanza. Ecco perché diciamo che O (n) è uguale a O (3n).

Quindi se hai bisogno anche di 1 passaggio, questo è O (1) ... e poiché il tuo programma richiede almeno 1 passaggio, il minimo che un algoritmo può percorrere è O (1). A meno che non lo facciamo, allora è O (0), penso? Se facciamo qualsiasi cosa, allora è O (1), ed è il minimo che può andare.

(Se scegliamo di non farlo, allora potrebbe diventare una domanda Zen o Tao ... nel regno della programmazione, O (1) è ancora il minimo).

O che ne dici di questo:

programmatore : capo, ho trovato il modo di farlo in O (1) volta!
capo : non c'è bisogno di farlo, stamattina siamo in bancarotta.
programmatore : oh, allora diventa O (0).


La tua battuta mi ha ricordato qualcosa del Tao della Programmazione: canonical.org/~kragen/tao-of-programming.html#book8 (8.3)
kenj0418,

Un algoritmo composto da zero passi è O (0). È un algoritmo molto pigro.
nalply

8

No, non è possibile:

Dato che n tende all'infinito in 1 / n alla fine otteniamo 1 / (inf), che è effettivamente 0.

Pertanto, la classe big-oh del problema sarebbe O (0) con un n massiccio, ma più vicino al tempo costante con un n basso. Questo non è sensato, in quanto l'unica cosa che può essere fatta in tempi più rapidi di quelli costanti è:

void nothing() {};

E anche questo è discutibile!

Non appena si esegue un comando, ci si trova almeno in O (1), quindi no, non possiamo avere una classe big-oh di O (1 / n)!


7

Che dire di non eseguire affatto la funzione (NOOP)? o usando un valore fisso. Questo conta?


16
Questo è ancora O (1) runtime.
Konrad Rudolph,

2
Bene, è ancora O (1). Non vedo come qualcuno possa capirlo, eppure sostengo in un'altra risposta che è possibile qualcosa di meno di NO-OP.
ShreevatsaR,

4
ShreevatsaR: non c'è assolutamente contraddizione. Sembra che tu non riesca a capire che la grande notazione O non ha nulla a che fare con il tempo impiegato nella funzione - piuttosto, descrive come quel tempo cambia con il cambiamento dell'input (sopra un certo valore). Vedi altri thread di commenti per ulteriori informazioni.
Konrad Rudolph,

Lo afferro perfettamente, grazie. Il punto - come ho fatto più volte nell'altro thread - è che se il tempo diminuisce con l'input, alla velocità O (1 / n), alla fine deve diminuire al di sotto del tempo impiegato da NOOP. Ciò dimostra che nessun algoritmo può essere O (1 / n) asintoticamente, anche se certamente il suo tempo di esecuzione può diminuire fino a un limite.
ShreevatsaR,

1
Sì ... come ho detto altrove, qualsiasi algoritmo che è O (1 / n) dovrebbe richiedere anche zero tempo per tutti gli input, quindi a seconda che si consideri che l'algoritmo null impieghi 0 tempo o meno, c'è un O (1 / n) algoritmo. Quindi se consideri NOOP come O (1), allora non ci sono algoritmi O (1 / n).
ShreevatsaR,

7

Uso spesso O (1 / n) per descrivere le probabilità che si riducono man mano che gli input diventano più grandi - ad esempio, la probabilità che una moneta giusta raggiunga la coda su log2 (n) flip è O (1 / n).


6
Questo non è ciò che è grande O però. Non puoi semplicemente ridefinirlo per rispondere alla domanda.
Zifre,

11
Non è una ridefinizione, è esattamente la definizione di grande O.
ShreevatsaR

10
Sono un informatico teorico di professione. Riguarda l'ordine asintotico di una funzione.
Dave,

4
Big O è una proprietà di una funzione reale arbitraria. La complessità temporale è solo una delle sue possibili applicazioni. La complessità dello spazio (la quantità di memoria di lavoro utilizzata da un algoritmo) è un'altra. Il fatto che la domanda riguardi gli algoritmi O (1 / n) implica che si tratta di uno di questi (a meno che non ce ne sia un altro applicabile agli algoritmi di cui non sono a conoscenza). Altre applicazioni includono ordini di crescita della popolazione, ad esempio in Conway's Life. Vedi anche en.wikipedia.org/wiki/Big_O_notation
Stewart

5
@Dave: la domanda non era se esistessero funzioni O (1 / n), che ovviamente esistono. Piuttosto, era se esistessero algoritmi O (1 / n), che (con la possibile eccezione della funzione null) non possono esistere
Casebash

6

O (1) significa semplicemente "tempo costante".

Quando aggiungi un'uscita anticipata a un loop [1] stai (in notazione big-O) trasformando un algoritmo O (1) in O (n), ma rendendolo più veloce.

Il trucco è in generale che l'algoritmo a tempo costante è il migliore e lineare è migliore quindi esponenziale, ma per piccole quantità di n, l'algoritmo esponenziale potrebbe effettivamente essere più veloce.

1: supponendo una lunghezza di elenco statica per questo esempio


6

Per chiunque abbia letto questa domanda e voglia capire di cosa tratta la conversazione, questo potrebbe aiutare:

|    |constant |logarithmic |linear|  N-log-N |quadratic|  cubic  |  exponential  |
|  n |  O(1)   | O(log n)   | O(n) |O(n log n)|  O(n^2) |  O(n^3) |     O(2^n)    |
|  1 |       1 |          1 |     1|         1|        1|       1 |             2 |
|  2 |       1 |          1 |     2|         2|        4|       8 |             4 |
|  4 |       1 |          2 |     4|         8|       16|      64 |            16 |
|  8 |       1 |          3 |     8|        24|       64|     512 |           256 |
| 16 |       1 |          4 |    16|        64|      256|   4,096 |         65536 |
| 32 |       1 |          5 |    32|       160|    1,024|  32,768 | 4,294,967,296 |
| 64 |       1 |          6 |    64|       384|    4,069| 262,144 |   1.8 x 10^19 |

5

Credo che gli algoritmi quantistici possano eseguire più calcoli "contemporaneamente" tramite sovrapposizione ...

Dubito che questa sia una risposta utile.


Sarebbe comunque un tempo costante, ovvero O (1), il che significa che occorre eseguire la stessa quantità di tempo per i dati di dimensione n come per i dati di dimensione 1.
spazio libero

2
E se il problema fosse una birra chiara? (ah. ah ah ah.)
Jeff Meatball Yang,

7
Sarebbe
un'ottima

1
Gli algoritmi quantistici possono eseguire più calcoli, ma è possibile recuperare solo il risultato di un calcolo e non è possibile scegliere quale risultato ottenere. Per fortuna, puoi anche eseguire operazioni su un registro quantistico nel suo insieme (ad esempio, QFT), quindi sei molto più propenso a trovare qualcosa :)
Gracenotes,

2
forse non è utile, ma ha il vantaggio di essere vero, il che lo mette al di sopra di alcune delle risposte più votate B-)
Brian Postow,

4

molte persone hanno avuto la risposta corretta (No) Ecco un altro modo per dimostrarlo: per avere una funzione, devi chiamare la funzione e devi restituire una risposta. Questo richiede un certo periodo di tempo costante. ANCHE SE il resto dell'elaborazione ha richiesto meno tempo per input più grandi, stampare la risposta (che è possibile supporre sia un singolo bit) richiede almeno un tempo costante.


2

Se esiste una soluzione, è possibile prepararla e accedervi a tempo costante = immediatamente. Ad esempio, utilizzando una struttura di dati LIFO se si conosce che la query di ordinamento è per l'ordine inverso. Quindi i dati sono già ordinati, dato che è stato scelto il modello appropriato (LIFO).


2

Quali problemi diventano più facili con l'aumentare della popolazione? Una risposta è qualcosa di simile a bittorrent in cui la velocità di download è una funzione inversa del numero di nodi. Contrariamente a un'auto, che rallenta quanto più la carichi, una rete di condivisione file come bittorrent accelera il maggior numero di nodi connessi.


Sì, ma il numero di nodi bittorrent è più simile al numero di processori in un computer parallelo. La "N" in questo caso sarebbe la dimensione del file che tenta di essere scaricato. Proprio come potresti trovare un elemento in una matrice non ordinata di lunghezza N in tempo costante se avessi N computer, puoi scaricare un file di dimensione N in tempo costante se tu avessi N computer che tentano di inviarti i dati.
Kibbee,

2

Non puoi andare sotto O (1), tuttavia O (k) dove k è minore di N è possibile. Li abbiamo chiamati algoritmi di tempo sublineare . In alcuni problemi, l'algoritmo del tempo sublineare può fornire solo soluzioni approssimative a un problema specifico. Tuttavia, a volte, una soluzione approssimativa va bene, probabilmente perché il set di dati è troppo grande o che è troppo costoso dal punto di vista computazionale per calcolare tutto.


1
Non sono sicuro di aver capito. Log (N) è minore di N. Significa che Log (N) è un algoritmo sublineare? E esistono molti algoritmi Log (N). Uno di questi esempi è trovare un valore in un albero binario. Tuttavia, questi sono ancora diversi da 1 / N, poiché Log (N) è sempre in aumento, mentre 1 / n è una funzione decrescente.
Kibbee,

Guardando la definizione, l'algoritmo del tempo sublineare è un qualsiasi algoritmo il cui tempo cresce più lentamente della dimensione N. Quindi include l'algoritmo del tempo logaritmico, che è Log (N).
Hao Wooi Lim,

2
Gli algoritmi di tempo sublineare possono fornire risposte esatte, ad esempio la ricerca binaria in un array ordinato su una macchina RAM.
A. Rex,

@UN. Rex: Hao Wooi Lim ha detto "In alcuni problemi".
LarsH,

1

Che dire di questo:

void FindRandomInList(list l)
{
    while(1)
    {
        int rand = Random.next();
        if (l.contains(rand))
            return;
    }
}

con l'aumentare della dimensione dell'elenco, il tempo di esecuzione previsto del programma diminuisce.


penso che tu non capisca il significato di O (n)
Markus Lausberg,

Non con la lista però, con array o hash dove constainsè O (1)
vava

ok, la funzione random può essere pensata come un array pigro, quindi in pratica stai cercando ogni elemento nella "lista casuale pigra" e controllando se è contenuta nell'elenco di input. Penso che questo sia peggio che lineare, non migliore.
hasen

Ha qualche punto se noti che int ha un insieme limitato di valori. Quindi, quando conterrei 2 <sup> 64 </sup> valori sarà istantaneo fino in fondo. Il che rende peggio di O (1) comunque :)
vava

1

O (1 / n) non è inferiore a O (1), in pratica significa che più dati hai, più l'algoritmo procede. Supponi di avere un array e di riempirlo sempre fino a 10 100 elementi se ha meno di quello e non fare nulla se c'è di più. Questo non è O (1 / n) ovviamente ma qualcosa come O (-n) :) Pessima notazione O-big non consente valori negativi.


1
"O (1 / n) non è inferiore a O (1)" - se una funzione f è O (1 / n), è anche O (1). E big-oh è molto simile a una relazione "minore di": è riflessiva, è transitiva e se abbiamo simmetria tra f e g i due sono equivalenti, dove big-theta è la nostra relazione di equivalenza. Tuttavia, le relazioni di ordinamento "reali" dell'ISTR che richiedono a <= b <= a implicano a = b, tuttavia, e netcraft ^ W wikipedia lo confermano. Quindi, in un certo senso, è giusto dire che effettivamente O (1 / n) è "minore di" O (1).
Jonas Kölker,

1

Come è stato sottolineato, a parte la possibile eccezione della funzione nulla, non ci possono essere O(1/n)funzioni, poiché il tempo impiegato dovrà avvicinarsi a 0.

Certo, ci sono alcuni algoritmi, come quello definito da Konrad, che sembrano essere meno che O(1)in un certo senso.

def get_faster(list):
    how_long = 1/len(list)
    sleep(how_long)

Se si desidera indagare su questi algoritmi, è necessario definire la propria misurazione asintotica o la propria nozione di tempo. Ad esempio, nel suddetto algoritmo, potrei consentire l'uso di un numero di operazioni "libere" per un determinato numero di volte. Nell'algoritmo sopra, se definisco t 'escludendo il tempo per tutto tranne che per il sonno, allora t' = 1 / n, che è O (1 / n). Probabilmente ci sono esempi migliori, poiché il comportamento asintotico è banale. In effetti, sono sicuro che qualcuno là fuori può trovare sensi che danno risultati non banali.


1

La maggior parte del resto delle risposte interpreta il big-O come esclusivamente relativo al tempo di esecuzione di un algoritmo. Ma dal momento che la domanda non l'ha menzionata, ho pensato che valesse la pena menzionare l'altra applicazione del big-O nell'analisi numerica, che riguarda l'errore.

Molti algoritmi possono essere O (h ^ p) o O (n ^ {- p}) a seconda che si parli di dimensioni del gradino (h) o numero di divisioni (n). Ad esempio, nel metodo di Eulero , cerchi una stima di y (h) dato che conosci y (0) e dy / dx (la derivata di y). La tua stima di y (h) è più accurata quanto più h è vicino a 0. Quindi per trovare y (x) per qualche x arbitraria, si prende l'intervallo da 0 a x, lo divide fino a n pezzi ed esegue il metodo di Eulero in ogni punto, per andare da y (0) a y (x / n) a y (2x / n) e così via.

Quindi il metodo di Eulero è quindi un algoritmo O (h) o O (1 / n), in cui h viene generalmente interpretato come una dimensione del gradino e n viene interpretato come il numero di volte in cui dividi un intervallo.

È inoltre possibile avere O (1 / h) in applicazioni di analisi numerica reali, a causa di errori di arrotondamento in virgola mobile . Minore è l'intervallo, maggiore è la cancellazione per l'implementazione di determinati algoritmi, maggiore perdita di cifre significative e quindi più errore, che viene propagato attraverso l'algoritmo.

Per il metodo di Eulero, se stai usando punti mobili, usa un passo e una cancellazione abbastanza piccoli e stai aggiungendo un piccolo numero a un numero grande, lasciando invariato il numero grande. Per algoritmi che calcolano la derivata sottraendo l'uno dall'altro due numeri da una funzione valutata in due posizioni molto vicine, approssimando y '(x) con (y (x + h) - y (x) / h), nelle funzioni regolari y (x + h) si avvicina a y (x) con conseguente grande annullamento e una stima per il derivato con meno cifre significative. Questo a sua volta si propaga a qualunque algoritmo per cui si richiede la derivata (ad esempio, un problema con il valore limite).


0

OK, ci ho pensato un po ', e forse esiste un algoritmo che potrebbe seguire questa forma generale:

Devi calcolare il problema del commesso viaggiatore per un grafico a 1000 nodi, tuttavia ti viene anche fornito un elenco di nodi che non puoi visitare. Man mano che l'elenco dei nodi non visibili si allarga, il problema diventa più facile da risolvere.


4
Quindi è diverso tipo di n in O (n). Con questo trucco potresti dire che ogni algoritmo ha O (q) dove q è il numero di persone che vivono in Cina per esempio.
vava,

2
Boyer-Moore è di tipo simile (O (n / m)), ma in realtà non è "migliore di O (1)", perché n> = m. Penso che lo stesso sia vero per il tuo "TSP invisibile".
Niki,

Anche in questo caso il tempo di esecuzione del TSP è NP-Complete, stai semplicemente rimuovendo i nodi dal grafico e quindi diminuendo efficacemente n.
Ed James,

0

Vedo un algoritmo che è O (1 / n) ammesso per un limite superiore:

Hai una grande serie di input che cambiano a causa di qualcosa di esterno alla routine (forse riflettono l'hardware o potrebbe anche essere un altro core nel processore che lo sta facendo.) E devi selezionarne uno casuale ma valido.

Ora, se non stesse cambiando, faresti semplicemente un elenco di elementi, scegline uno a caso e otterrai O (1) tempo. Tuttavia, la natura dinamica dei dati preclude la creazione di un elenco, è sufficiente sondare casualmente e testare la validità del probe. (E nota che intrinsecamente non esiste alcuna garanzia che la risposta sia ancora valida quando viene restituita. Questo potrebbe avere ancora degli usi - diciamo, l'intelligenza artificiale per un'unità in un gioco. Potrebbe sparare a un bersaglio che è scomparso mentre era premendo il grilletto.)

Ciò ha una prestazione nel caso peggiore dell'infinito, ma una prestazione nel caso medio che diminuisce quando lo spazio dati si riempie.


0

Nell'analisi numerica, gli algoritmi di approssimazione dovrebbero avere una complessità asintotica sub-costante nella tolleranza di approssimazione.

class Function
{
    public double[] ApproximateSolution(double tolerance)
    {
        // if this isn't sub-constant on the parameter, it's rather useless
    }
}

intendi davvero una sotto costante o sublineare? Perché gli algoritmi di approssimazione dovrebbero essere sub costanti? E cosa significa anche ??
LarsH,

@LarsH, l'errore degli algoritmi di approssimazione è proporzionale alla dimensione del passo (o alla sua potenza positiva), quindi più piccola è la dimensione del passo, minore è l'errore. Ma un altro modo comune per esaminare un problema di approssimazione è l'errore rispetto a quante volte un intervallo viene diviso. Il numero di partizioni di un intervallo è inversamente proporzionale alla dimensione del passo, quindi l'errore è inversamente proporzionale alla potenza positiva del numero di partizioni: quando si aumenta il numero di partizioni, l'errore diminuisce.
Andrew Lei,

@AndrewLei: Wow, una risposta quasi 7 anni dopo! Capisco la risposta di Sam ora meglio di allora. Grazie per aver risposto.
LarsH

0

Immagino che meno di O (1) non sia possibile. Ogni tempo impiegato da algo è definito come O (1). Ma per O (1 / n) che ne dici della funzione qui sotto. (So ​​che ci sono già molte varianti presentate in questa soluzione, ma immagino che abbiano tutti dei difetti (non importanti, spiegano bene il concetto). Quindi eccone una, solo per ragioni di argomento:

def 1_by_n(n, C = 10):   #n could be float. C could be any positive number
  if n <= 0.0:           #If input is actually 0, infinite loop.
    while True:
      sleep(1)           #or pass
    return               #This line is not needed and is unreachable
  delta = 0.0001
  itr = delta
  while delta < C/n:
    itr += delta

Pertanto, all'aumentare di n, la funzione richiederà sempre meno tempo. Inoltre è garantito che se l'ingresso è effettivamente 0, allora la funzione impiegherà un'eternità a tornare.

Si potrebbe sostenere che sarà limitato dalla precisione della macchina. quindi sinc eit ha un limite superiore è O (1). Ma possiamo anche bypassarlo, prendendo input di n e C in stringa. E l'aggiunta e il confronto vengono eseguiti su stringa. L'idea è che, con questo, possiamo ridurre n in modo arbitrario. Pertanto il limite superiore della funzione non è limitato, anche quando ignoriamo n = 0.

Credo anche che non possiamo semplicemente dire che il tempo di esecuzione è O (1 / n). Ma dovremmo dire qualcosa come O (1 + 1 / n)


-1

Potrebbe essere possibile costruire un algoritmo O (1 / n). Un esempio potrebbe essere un ciclo che itera un multiplo di f (n) -n volte in cui f (n) è una funzione il cui valore è garantito essere maggiore di n e il limite di f (n) -n quando n si avvicina all'infinito è zero. Anche il calcolo di f (n) dovrebbe essere costante per tutti n. Non so a mano come sarebbe f (n) o quale applicazione avrebbe un tale algoritmo, a mio avviso tuttavia tale funzione potrebbe esistere ma l'algoritmo risultante non avrebbe altro scopo che dimostrare la possibilità di un algoritmo con O (1 / n).


Il tuo loop richiede un controllo che richiede almeno un tempo costante, quindi l'algoritmo risultante ha almeno la complessità O (1).
Stefan Reich,

-1

Non conosco algoritmi ma le complessità inferiori a O (1) appaiono in algoritmi randomizzati. In realtà, o (1) (piccola o) è inferiore a O (1). Questo tipo di complessità appare di solito negli algoritmi randomizzati. Ad esempio, come hai detto, quando la probabilità di un evento è dell'ordine di 1 / n, lo denotano con o (1). O quando vogliono dire che qualcosa accade con alta probabilità (es. 1 - 1 / n) lo denotano con 1 - o (1).


-2

Se la risposta è la stessa indipendentemente dai dati di input, hai un algoritmo O (0).

o in altre parole - la risposta è nota prima che vengano inviati i dati di input - la funzione potrebbe essere ottimizzata - quindi O (0)


Veramente? Dovresti comunque restituire un valore, quindi non sarebbe comunque O (1)?
Joachim Sauer,

7
no, O (0) implicherebbe che impiega zero tempo per tutti gli ingressi. O (1) è tempo costante.
Pete Kirkham,

-2

La notazione Big-O rappresenta lo scenario peggiore per un algoritmo che non è la stessa cosa del suo tipico tempo di esecuzione. È semplice dimostrare che un algoritmo O (1 / n) è un algoritmo O (1). Per definizione,
O (1 / n) -> T (n) <= 1 / n, per tutti n> = C> 0
O (1 / n) -> T (n) <= 1 / C, poiché 1 / n <= 1 / C per tutti n> = C
O (1 / n) -> O (1), poiché la notazione Big-O ignora le costanti (ovvero il valore di C non ha importanza)


No: la notazione O grande viene anche usata per parlare di scenari a tempo medio e attesi (e persino nel migliore dei casi). Il resto segue.
Konrad Rudolph,

La notazione 'O' definisce sicuramente un limite superiore (in termini di complessità algoritmica, questo sarebbe il caso peggiore). Omega e Theta sono usati per indicare il caso migliore e medio, rispettivamente.
Roland Ewald,

2
Roland: È un'idea sbagliata; il limite superiore non è la stessa cosa del caso peggiore, i due sono concetti indipendenti. Considera il runtime atteso (e medio) hashtable-containsdell'algoritmo che può essere indicato come O (1) - e il caso peggiore può essere dato in modo molto preciso come Theta (n)! Omega e Theta possono semplicemente essere usati per indicare altri limiti, ma per dirlo di nuovo : non hanno nulla a che fare con il caso medio o migliore.
Konrad Rudolph,

Konrad: True. Tuttavia, Omega, Theata e O vengono generalmente utilizzati per esprimere i limiti e, se si considerano tutti i possibili input, O rappresenta il limite superiore, ecc.
Roland Ewald,

1
Il fatto che O (1 / n) sia un sottoinsieme di O (1) è banale e segue direttamente la definizione. Infatti, se una funzione g è O (h), anche qualsiasi funzione f che è O (g) è anche O (h).
Tobias,

-2

Nulla è più piccolo di O (1) La notazione Big-O implica il più grande ordine di complessità per un algoritmo

Se un algoritmo ha un tempo di esecuzione di n ^ 3 + n ^ 2 + n + 5, allora è O (n ^ 3) I poteri inferiori non contano affatto qui perché come n -> Inf, n ^ 2 sarà irrilevante rispetto a n ^ 3

Allo stesso modo come n -> Inf, O (1 / n) sarà irrilevante rispetto a O (1), quindi 3 + O (1 / n) sarà lo stesso di O (1) rendendo così O (1) il più piccolo possibile computazionale complessità


-2
inline void O0Algorithm() {}

1
Sarebbe un algoritmo O (1).
Lasse V. Karlsen,

2
Anche quello, ma il punto è che non è Ω (1). E perché la mia risposta è stata ridotta? Se pensi che mi sbagli, che ne dici di spiegare?
Stewart,

Ho chiesto altrove se, in fondo, questa risposta molto è corretta o meno, e sembra essere contestato: stackoverflow.com/questions/3209139/...
jyoungdev

Beh, è ​​in linea, quindi puoi considerarlo O (0). Tuttavia, tutti gli algoritmi O (0) sono banali (non fanno nulla), quindi ... non è una risposta molto interessante.
Stefan Reich,

@StefanReich È vero, non è una risposta molto interessante, ma è una risposta.
Stewart,

-2

Ecco un semplice algoritmo O (1 / n). E fa anche qualcosa di interessante!

function foo(list input) {
  int m;
  double output;

  m = (1/ input.size) * max_value;  
  output = 0;
  for (int i = 0; i < m; i++)
    output+= random(0,1);

  return output;
}

O (1 / n) è possibile in quanto descrive come cambia l'output di una funzione data la dimensione crescente dell'input. Se stiamo usando la funzione 1 / n per descrivere il numero di istruzioni eseguite da una funzione, non è necessario che la funzione prenda zero istruzioni per qualsiasi dimensione di input. Piuttosto, è che per ogni dimensione di input, n al di sopra di una certa soglia, il numero di istruzioni richieste è limitato da una costante positiva moltiplicata per 1 / n. Poiché non esiste un numero effettivo per il quale 1 / n è 0 e la costante è positiva, non vi è alcun motivo per cui la funzione sia vincolata a prendere 0 o meno istruzioni.


1
Poiché O (1 / n) scenderà sotto la linea orizzontale = 1, e quando n raggiungerà l'infinito, il codice eseguirà comunque un determinato numero di passaggi, questo algoritmo è un algoritmo O (1). La notazione Big-O è una funzione di tutte le diverse parti dell'algoritmo e sceglie quella più grande. Dal momento che il metodo eseguirà sempre alcune delle istruzioni, quando n raggiunge l'infinito, rimarrai sempre con le stesse istruzioni che verranno eseguite ogni volta, e quindi il metodo verrà eseguito in tempo costante. Certo, non passerà molto tempo, ma non è rilevante per la notazione Big-O.
Lasse V. Karlsen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.