Trovare il numero di elementi più piccoli per ciascun elemento in un array in modo efficiente


9

Sono bloccato su questo problema:

Dato un array A dei primi n numeri naturali casualmente permutati, viene costruito un array B , in modo tale che B(k) è il numero di elementi da A(1) ad A(k1) che sono più piccoli di A(k) .

i) Dato A puoi trovare B in O(n) tempo?
ii) Dato B riesci a trovare A in O(n) tempo?

Qui, B(1)=0 . Per un esempio concreto:

|A843172965B000031644|

Qualcuno può aiutarmi? Grazie.


Ho trovato questo: codifiche di permutazione computazionale che fornisce algoritmi per questi problemi. Almeno penso che siano gli stessi problemi. O(nlogn)
Realz Slaw,

@Merbs Questo suggerimento che hai dato significa che hai una soluzione?
AJed,

1
@AJed, significa che ho un algoritmo, anche se ci vuole per l'algoritmo semplice senza spazio e O ( n log n ) se ci è concesso spazio. Al momento, mi sto proponendo che non sia possibile in O ( n ) ed entrambi sono lo stesso algoritmo. O(n2)O(nlogn)O(n)
Merbs,

@Merbs. Sento che il tuo suggerimento può portare sulla strada giusta. Ho anche una soluzione (seguendo il tuo suggerimento). Immagino che ci sia un trucco nell'analisi che lo porta ad .. Penso che il trucco sia la conoscenza che va solo da 1: . O(n)UNn
AJed,

2
Questo documento fornisce anche un algoritmo . Sei sicuro che esista un algoritmo per questo? O(nlogn)O(n)
Realz Slaw,

Risposte:


1

L'algoritmo ingenuo per determinare da :BA

Per , determinare il valore di B ( k ) confrontando ogni A ( i ) con A ( k ) per i = 1 , , k e contando quelli che soddisfano A ( i ) < A ( k ) .k=1,,nB(k)A(i)A(k)i=1,,kA(i)<A(k)

Questo algoritmo confronta con tutti gli altri ( n - 1 volte), A ( 2 ) con n - 2 altri, ecc. Quindi il numero totale di confronti è ( n - 1 ) ( n - 2 )A(1)n1A(2)n2 . Ma non è il massimo che possiamo fare. Ad esempio, guardandoB(n), non dobbiamo fare paragoni! B(n)=A(n)-1perché sono ipriminnumeri naturali, ed è garantito (indipendentemente dalla permutazione) checi saranno i numeri naturali inferiorin-1. Che dire diB(n-1)? Invece di controllare daA(1)aA(n(n1)(n2)2B(n)B(n)=A(n)1 nn1B(n1)A(1) , potremmo semplicemente controllare A ( n ) . Questo è:A(n2)A(n)

Per , utilizzare l'algoritmo sopra; per k=nk=1,,n2usa l'algoritmo inverso: determinaB(k)impostandolo inizialmente suA(n)-1e quindi sottraendo1per ogni voceA(i)peri=k+1,,nche è minore diA(k).k=n2,,nB(k)A(n)11A(i)io=K+1,...,nUN(K)

Ciò richiederebbe passaggi, che è ancoraO(n2). Nota anche che nel costruireAdaB, seB(n)=A(n)-1,alloraA(n)=B(n)+1.2×(n2-1)(n2-2)2=(n-2)(n-4)4O(n2)UNBB(n)=UN(n)-1A(n)=B(n)+1

Ma ora per più finezza. Se ci viene concesso dello spazio aggiuntivo o l'ordinamento sul posto, possiamo ordinare i numeri mentre li stiamo confrontando. Ad esempio:

|A843172965S987432165B0000316|

Invece di controllarli tutti (o controllarli in ordine), potremmo usare la ricerca binaria per determinare ogni . Tuttavia, l'ordinamento richiede ancora tempo O ( n registro n ) .B(k)O(nlogn)


Questa era solo la mia prima idea; anche se mi rendo conto che il problema è più interessante di quanto inizialmente gli abbia dato credito. E non ho ancora avuto l'opportunità di leggere i risultati di Realz Slaw, quindi l'algoritmo potrebbe essere spento.
Merbs,

0

Invece di determinare ogni uno alla volta, possiamo guardare avanti e passare attraverso ogni numero in A una volta ! Ma useremo n spazio:B(k)A n

|A123456789B800000000104000011112030001222230101123333407011233345320123444561901234445666012344567450123456784|

Potremmo risparmiare ancora più tempo non aggiornando quelli che sono già stati determinati (vale a dire, non ha senso aggiornare dopo il primo passaggio), ma nel caso peggiore, dobbiamo ancora aggiornare ( n ) ( n + 2 )8 volte(n)(n+2)2


0

sia I che II sono risolvibili usando #next_greater_element che ho spiegato qui . ma è un po 'più difficile del semplice problema, ma prima della soluzione devi imparare il prossimo elemento maggiore:

  1. considera che abbiamo un vettore per ogni elemento di name it S i per element i . ora, una volta eseguito l'algoritmo più prossimo partendo da destra a sinistra ma tranne modificando elemento i in una sua prossima maggiore indice di elemento, spingere S i elementi che ho è la loro successiva maggiore element.then iterate sulla matrice sinistra a destra e poi B [ i ] = x j = 0 ( S i [ j ] + 1 ) dove xASiiiASiiB[i]=j=0x(Si[j]+1)xSioΘ(n)Θ(n)Θ(n)

O(1)o(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.