Algoritmi: come posso sommare O (n) e O (nlog (n)) insieme?


22

Ho il seguente algoritmo che trova i duplicati e li rimuove:

public static int numDuplicatesB(int[] arr) {
    Sort.mergesort(arr);
    int numDups = 0;
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] == arr[i - 1]) {
            numDups++;
} }
    return numDups;
}

Sto cercando di trovare la peggiore complessità temporale di questo. So che mergesort è nlog(n), e nel mio ciclo for sto iterando sull'intero set di dati in modo che contasse come n. Non sono sicuro di cosa fare con questi numeri. Dovrei semplicemente sommarli? Se dovessi farlo, come lo farei?


1
Nota a margine: è possibile utilizzare una tabella hash per farlo in O (n) a seconda dei requisiti di memoria.
corsiKa

Risposte:


67
O(n) + O(n log(n)) = O(n log(n))

Per la complessità di Big O, tutto ciò che ti interessa è il termine dominante. n log(n)domina nquindi questo è l'unico termine a cui tieni.


4
Un altro modo di pensare a questo è immaginare che la tua elaborazione O (n) fosse davvero O (n log n), come se avessi fatto due tipi indipendenti. Quindi avresti 2 * O (n log n). Ma le costanti scompaiono, quindi sei di nuovo su O (n log n).
Jonathan Eunice,

4
@Jonathan Anche se funziona in pratica, è vero che O (n) non è uguale a O (n log (n)), quindi non consiglierei di usarlo su base regolare.
Aza,

17
@Emrakul in realtà penso che il ragionamento sia teoricamente valido oltre che pratico. O (n) è un sottoinsieme proprio di O (n log (n)). Quindi se f (n) appartiene a O (n) appartiene anche a O (n log (n)).
emory

17
Va notato che quando diciamo f(n) is O(g(n))che stiamo davvero dicendo che è la funzione f is a member of the set of functions that grows at the rate of at most g(n) over the long term. Questo significa che tutti i membri O(n)sono anche membri di O(n*log(n)). Le +espressioni in come in O(f(n)) + O(g(n))realtà si riferiscono a set union (di cui sei davvero pedante, dovresti davvero usare ∪).
Lie Ryan,

3
@LieRyan In origine, non è impostata l'unione, ma insieme sum: A + B = { a + b | a in A, b in B }. Succede che per gli insiemi della forma O(g(n))questo sia lo stesso di un insieme di insiemi, poiché uno degli insiemi è sempre un sottoinsieme dell'altro, ed entrambi sono invarianti rispetto alle somme (cioè A + A = A). (Oops, Nate ha scritto essenzialmente lo stesso).
Paŭlo Ebermann,

56

Ragioniamo in questo modo e ricordiamo la definizione di O. Quello che userò è per il limite all'infinito.

È corretto affermare che si eseguono due operazioni con corrispondenti limiti asintotici di O(n)e O(nlog(n))che combinarli in un unico limite non è così semplice come aggiungere le due funzioni. Sai che la tua funzione richiede almeno O(n)tempo e anche almeno O(nlog(n))tempo. Quindi, in realtà la classe di complessità per la vostra funzione è l'unione di O(n)e O(nlog(n)), ma O(nlog(n))è un superset di O(n)modo davvero è solo O(nlog(n)).


12
+1 questa dovrebbe essere la risposta. Descrive la risposta più precisamente usando i termini compsci.

5

Se lo avessi impostato a lungo, sembrerebbe più o meno così:

Supponiamo che il tempo totale sia: an + bn log (n), dove aeb sono costanti (ignorando i termini di ordine inferiore).

Come n va all'infinito (an + bn log (n)) / n log (n) -> a / log (n) + b -> b

Quindi il tempo totale è O (bn log (n)) = O (n log (n)).


2

Inizia con la definizione di O ():

O (n log n) significa "inferiore a C n log n, se n è grande".

O (n) significa "minore di D n, se n è grande".

Se si aggiungono entrambi, il risultato è inferiore a C n log n + D n <C n log n + D n log n <(C + D) n log n = O (n log n).

In generale, se f (n)> C g (n) per n grande e qualche C> 0, allora O (f (n)) + O (g (n)) = O (f (n)). E dopo aver fatto alcuni casi usando la definizione di O (), saprai cosa puoi e cosa non puoi fare.


1

La notazione O grande è definita come un set:

inserisci qui la descrizione dell'immagine

Quindi inserisci qui la descrizione dell'immaginecontiene tutte le funzioni che sono - a partire da alcuni punti arbitrari di grandi dimensioni inserisci qui la descrizione dell'immagine- sempre più piccole di g.

Ora, quando hai una funzione che è attiva inserisci qui la descrizione dell'immaginee quindi ne esegui un'altra che aumenta più lentamente di g, aumenta sicuramente più lentamente di 2g. Quindi eseguire qualcosa di più lento di g non cambierà la classe di complessità.

Più formalmente:

f, h \ in \ mathcal {O} (g) \ Rightarrow (f + h) \ in \ mathcal {O} (g)

Puoi dimostrarlo facilmente.

TL; DR

È ancora n log (n)

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.