2015-09-07 11 views
8

Cercando di rispolverare la comprensione del Big-O per un test (Una comprensione di base del Big-O richiesta ovviamente) Sto arrivando e stava facendo alcuni problemi di pratica nel mio libro.Notazione Big-Oh per un singolo ciclo while che copre due metà di un array con due iterator vars

Mi hanno dato il seguente frammento

public static void swap(int[] a) 
{ 
    int i = 0; 
    int j = a.length-1; 

    while (i < j) 
    { 
     int temp = a[i]; 
     a[i] = a[j]; 
     a[j] = temp; 
     i++; 
     j--; 
    } 
} 

abbastanza facile da capire che penso. Ha due iteratori che coprono metà della matrice con una quantità fissa di lavoro (che penso li tocchi entrambi a O (n/2))

Pertanto O (n/2) + O (n/2) = O (2n/2) = O (n)

Ora, per favore perdonami, poiché questa è la mia attuale comprensione e questo è stato il mio tentativo di risolvere il problema. Ho trovato molti esempi di big-o online ma nessuno che è abbastanza come questo in cui gli iteratori incrementano e modificano l'array praticamente nello stesso tempo.

Il fatto che abbia un ciclo mi fa pensare che sia O (n) comunque.

Qualcuno mi dispiacerebbe chiarire questo per me?

Grazie

+0

FYI: anche se si esegue solo l'iterazione su metà di un array, ad esempio 'sumOddIndexElements()', è ancora O (n). Il fattore costante di 1/2 va via. Quando inizi ad analizzare algoritmi più complessi, è utile passare dai conteggi esatti al big-O all'inizio dell'analisi. Quindi i passaggi intermedi diventano più semplici perché puoi eliminare termini. OSSIA se una subroutine fa funzionare O (n) + O (log n), è possibile ridurla immediatamente a O (n) per il resto dell'analisi. – japreiss

+0

@japreiss Mi dispiace, non sto cercando di essere ridondante con qualsiasi mezzo, ma la tua ultima frase mi ha confuso un po '. Se ho capito bene, O (log n) diventerà insignificante a O (n) ad un certo punto che non vale la pena calcolare nell'efficienza temporale e quindi lo abbandoniamo? – Habitat

+0

Con la definizione di O grande, quando si aggiungono termini è sempre possibile eliminare tutto tranne i più grandi asintoticamente. Puoi provare che 'n + log n <2n' ma' 2n' è O (n). Quindi sì, è insignificante, in un modo molto ben definito. – japreiss

risposta

7

Il fatto che ha un ciclo mi sta facendo che sia O (n) in ogni caso.

Questo è corretto. Non perché sta creando un ciclo, ma perché è un ciclo che dipende dalla dimensione dell'array di un fattore costante: la notazione O grande ignora qualsiasi fattore costante. O(n) significa che l'unica influenza sull'algoritmo si basa sulla dimensione dell'array. Che in realtà ci vuole la metà di quel tempo, non importa per il big-O.

In altre parole: se il vostro algoritmo prende tempo n+X, Xn, Xn + Y saranno tutti scendere a O-grande O(n).

Prende differente se la dimensione del ciclo viene cambiata diverso da un fattore costante, ma come una funzione logaritmica o esponenziale di n, ad esempio se la dimensione è 100 e loop è 2, la dimensione è 1000 e loop è 3, la dimensione è 10000 e il ciclo è 4. In tal caso, sarebbe, ad esempio, O(log(n)).

Sarebbe anche diverso se il ciclo fosse indipendente dalla dimensione. Ad esempio, se si eseguono sempre il ciclo 100 volte, indipendentemente dalla dimensione del ciclo, l'algoritmo sarà O(1) (ad esempio, opererà in un tempo costante).

Io vorrei sapere se l'equazione mi è venuta arrivare era da qualche parte nel ballpark di essere corretto.

Sì. Infatti, se l'equazione finisce per essere una forma di n * C + Y, dove C è una costante e Y è un altro valore, il risultato è O(n), indipendentemente dal fatto vedere è maggiore di 1 o inferiori 1.

+0

Grazie per la risposta. Mi stavo anche chiedendo se l'equazione che mi è venuta in mente fosse da qualche parte nel campo di battaglia di essere corretta. Aiuta a pensarci in modo matematico come questo, ma sto facendo un tentativo al buio con esso. Qualche convalida su quell'aspetto particolare sarebbe grandiosa. Suppongo che sia "O (n/2) + O (n/2) o solo O (n/2) e poi ignoro il/2 tutto insieme" – Habitat

+0

@Habitat: ho aggiornato la risposta per rispondere;) . – Abel

1

Hai ragione per il ciclo. Loop determinerà il Big O. Ma il ciclo funziona solo per metà della matrice.

Quindi è. 2 + 6 * (n/2)

Se rendiamo n molto grande, altri numeri sono veramente piccoli. Quindi non contano. Quindi è O (n).

Diciamo che stai eseguendo 2 loop separati. 2 + 6 * (n/2) + 6 * (n/2). In tal caso sarà di nuovo O (n).

Ma se eseguiamo un ciclo annidato. 2+ 6 * (n * n). Quindi sarà O (n^2)

Rimuovere sempre le costanti e fare i conti. Hai avuto l'idea.

+0

Quindi lascia che lo rompa molto velocemente. Sono 2 operazioni iniziali + 6 operazioni per ogni iterazione volte le iterazioni totali? – Habitat

+0

Sì! hai ragione. – Sorter

+0

L'esempio con 'O (2n)' continua a essere come 'O (n)', perché dipende ancora singolarmente dalle dimensioni. Altrimenti, se due anelli con un risultato diverso, metà loop dovrebbe produrre un risultato diverso nella notazione O grande. – Abel

0

Come j-i diminuisce di 2 unità su ogni iterazione, N/2 di esse vengano prese (supponendo N=length(a)).

Quindi il tempo di esecuzione è effettivamente O(N/2). E O(N/2) è strettamente equivalente a O(N).

Problemi correlati