2013-01-07 17 views
13

ho pensato un problema che è la seguente:Finding più vicino numero in una gamma

Abbiamo un array A di interi di dimensione n, e noi abbiamo prova cause T e in tutti i casi di test ci viene dato un certo numero m e un intervallo [s, e] cioè ci viene dato se ed e dobbiamo trovare il numero più vicino di m nell'intervallo di quell'array (A [s] -A [e]).

È possibile assumere array indicizzati da 1 a n.

Ad esempio:

A = {5, 12, 9, 18, 19} 
    m = 13 
    s = 4 and e = 5 

Quindi la risposta dovrebbe essere 18.

Vincoli:

n<=10^5 
t<=n 

Tutto quello che posso pensare è una (n) soluzione per ogni caso di test O, e penso che esista una soluzione migliore.

+2

Se non è ordinato in alcun modo, è necessario accedere a tutti i valori compresi tra A [s] e A [e], quindi O (n) è.O piuttosto O (e-s), suppongo. – femtoRgon

+0

@femtoRgon lo so, ma con l'uso di qualsiasi struttura dati penso che sia possibile (basti pensare ma non sicuro). –

+0

Dato che hai specificato un limite di dimensioni massime (10^5), non è la complessità O (1) - cioè il tempo costante? – Chris

risposta

9

Questo è uno schizzo preliminare: Crea un segment tree dai dati. In ogni nodo, oltre ai soliti dati come gli indici sinistro e destro, si memorizzano anche i numeri trovati nel sotto-albero radicato in quel nodo, memorizzati nell'ordine ordinato. È possibile ottenere ciò quando si costruisce l'albero del segmento in ordine ascendente. Nel nodo appena sopra la foglia, si memorizzano i due valori foglia nell'ordine ordinato. In un nodo intermedio, si mantengono i numeri nel figlio sinistro e nel figlio destro, che è possibile unire insieme utilizzando la fusione standard. Ci sono nodi O (n) nell'albero e il mantenimento di questi dati dovrebbe richiedere O (nlog (n)).

Una volta ottenuto questo albero, per ogni query, percorrere il percorso fino a raggiungere il nodo o i nodi appropriati nell'intervallo specificato ([s, e]). Come mostra il tutorial, uno o più nodi diversi si combinano per formare l'intervallo specificato. Poiché la profondità dell'albero è O (log (n)), è il tempo per query per raggiungere questi nodi. Ogni query dovrebbe essere O (log (n)). Per tutti i nodi che si trovano completamente all'interno dell'intervallo, trovare il numero più vicino utilizzando la ricerca binaria nell'array ordinato memorizzato in tali nodi. Di nuovo, O (log (n)). Trova il più vicino tra tutti questi, e questa è la risposta. Pertanto, è possibile rispondere a ciascuna query nel tempo O (log (n)).

Il tutorial I link contiene altre strutture dati, come la tabella sparse, che sono più facili da implementare e dovrebbero fornire O (sqrt (n)) per query. Ma non ho pensato molto a questo.

+0

Come decidi quali nodi inserire nell'albero? Non è possibile aggiungere tutti gli indici sinistro e destro possibili. – Chris

+0

Un albero del segmento viene creato sopra l'array (ogni elemento dell'array è una foglia) e ogni due nodi foglia vengono combinati per fornire un nodo di livello successivo e così via. Costruisci l'intero albero sull'array come indicato nel tutorial. Quindi, la ricerca di dati aggregati in un determinato intervallo richiede l'attraversamento di almeno due rami nell'albero. – mayank

+0

Giusto, capito adesso. Mi dispiace, ho lavorato con gli alberi dei segmenti, ma in qualche modo non potevo immaginare come si adattassero a questo problema. – Chris

-1

Sono abbastanza sicuro che non esiste una soluzione più veloce. Una leggera variazione del tuo problema è:

Non c'è una matrice A, ma ogni caso di test contiene una matrice non ordinata di numeri da cercare. (La sezione dell'array di A da s a e).

In tal caso, non esiste chiaramente un modo migliore di una ricerca lineare per ogni caso di test.

Ora, in che modo il problema originale è più specifico della variante sopra riportata? L'unica informazione aggiunta è che tutte le fette provengono dallo stesso array. Non penso che questo ulteriore vincolo possa essere usato per un aumento di velocità algoritmico.

MODIFICA: Sono in posizione corretta. La struttura dati dell'albero del segmento dovrebbe funzionare.

+2

Questa non è una leggera variazione, è una grande differenza. Quando hai 'A' in anticipo, potresti essere in grado di creare una struttura dati durante la pre-elaborazione che consentirà ricerche più veloci. – interjay

+0

La mia argomentazione era che non esiste una tale struttura dati, ma l'idea dell'albero del segmento in una risposta diversa mi ha convinto diversamente. – Chris

-1

ordina l'array e effettua la ricerca binaria. complessità: o (nlogn + logn * t)

+1

non funzionerà - hai gli indici dell'array originale come parte della query. Leggi di nuovo la dichiarazione. –

Problemi correlati