2012-01-06 6 views
5

Una domanda di intervista:Progettare un algoritmo, trovare la parola più frequentemente usata in un libro

Trova la parola più frequentemente usata in un libro.

mia idea:

utilizzare una tabella hash, traverse e segnare la tabella di hash.

Se la dimensione del libro è nota, se viene trovata una parola> 50%, saltare le eventuali nuove parole nel seguente traversamento e contare solo le parole vecchie. Cosa succede se la dimensione del libro è sconosciuta?

È O (n) e O (n) tempo e spazio.

Qualche idea migliore?

Grazie

+1

Modificato il tag, fammi sapere se non appropriato. Non sembra una domanda specifica per la lingua. –

+2

Hashing è un buon euristico, ma non ottiene una risposta esatta (infatti due stringhe possono essere hash per lo stesso int) Inoltre, se si desidera trovare la maggior parte delle parole di frequenza, penso che si debbano saltare parole come 'the, then ,. ..' perché saranno più frequenti con alta probabilità, ma non è una buona notizia che tutti sappiano che questo libro ha "la" più frequentemente delle parole. –

+1

user1002288, stai ricevendo molti consigli sbagliati su questo thread. Quasi tutte le risposte provengono da una prospettiva pratica/attuativa che probabilmente non è ciò che l'intervistatore sta cercando. Probabilmente vorrai guardare questo da una prospettiva teorica. Se fai questa domanda su http://cstheory.stackexchange.com/ probabilmente otterrai risposte migliori. – Spike

risposta

2

solito Heap è la-struttura di dati che si adatta bene quando dobbiamo determinare qualcosa come più/meno utilizzato.

Anche lo Python;s Counter.nlargest utilizzato per questi scopi viene implementato tramite la struttura dei dati di heap.

Un binario Mucchio dati-struttura ha la seguente Complessità

CreateHeap - O(1) 
FindMin - O(1) 
deleteMin - O(logn) 
Insert - O(logn) 

ho eseguito una comparition su Hash (utilizzando il dizionario predefinito in Python) e Heap (utilizzando Collections.Counter.nlargest in Python) e l'hash è carenatura leggermente migliore di Heap.

>>> stmt1=""" 
import collections, random 
somedata=[random.randint(1,1000) for i in xrange(1,10000)] 
somehash=collections.defaultdict(int) 
for d in somedata: 
    somehash[d]+=1 
maxkey=0 
for k,v in somehash.items(): 
    if somehash[maxkey] > v: 
     maxkey=k 
""" 
>>> stmt2=""" 
import collections,random 
somedata=[random.randint(1,1000) for i in xrange(1,10000)] 
collections.Counter(somedata).most_common(1) 
""" 
>>> t1=timeit.Timer(stmt=stmt1) 
>>> t2=timeit.Timer(stmt=stmt2) 
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=10)/10) 
38168.96 usec/pass 
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=10)/10) 
33600.80 usec/pass 
+0

Per rendere la risposta più completa, ti dispiacerebbe precisare la complessità di tempo e spazio di una soluzione basata su heap? Grazie. – NPE

+0

@Aix, in realtà il collegamento wiki aveva le informazioni. In qualsiasi modo lo aggiungerò qui che avrà più senso – Abhijit

+0

'stmt1' può essere ottimizzato:' max (((v, k) per k, v in somehash.iteritems())) ' – reclosedev

1

C'è una generalizzazione del vostro Optimization, se la dimensione del libro è conosciuto e qualsiasi parola avete visto ha un conteggio> il numero rimanente di parole + prossimo-Record, il vostro attuale di parola più elevata-contati è la risposta.

2

Per determinare la complessità, penso che sia necessario considerare due variabili, n = numero totale di parole, m = numero di parole univoche. Immagino che la migliore complessità del caso uscirà vicino a O (n log (m)) per la velocità, e O (m) per l'archiviazione, assumendo ogni volta che si itera su ciascuna di n parole, e si costruisca e cerchi in base a una tabella hash o altra struttura di questo tipo che alla fine contiene m elementi.

1

La soluzione è corretta, veloce e probabilmente la migliore/più semplice da un punto di vista pratico.

Le soluzioni dell'altro poster presentano una complessità temporale peggiore rispetto alla soluzione. Per un hash, come stai usando, la complessità del tempo è davvero O (n). Ogni inserimento è O (1) e ci sono n parole, quindi la fase di inserimento costa O (n). L'iterazione e la ricerca del massimo è quindi O (n). Lo spazio è anche O (n) come hai detto.

Nota che non sarai in grado di terminare il tuo algoritmo in anticipo utilizzando la soluzione di Chris perché la ricerca nella tua tabella hash è costosa e non è possibile per te eseguire questa operazione in tempo O (1) dopo ogni inserimento.

Un heap avrà un costo maggiore in termini di tempo perché è necessario mantenere l'heap durante ogni inserimento. Un inserimento heap è O (log (n)) e quindi il costo totale per l'inserimento sarà O (nlog (n)).

+1

Una cosa che probabilmente hai ignorato. La complessità nella generazione di una chiave hash. – Abhijit

+0

Stai dicendo che la generazione di una chiave hash richiede più di tempo O (n)? Spiega per favore. L'applicazione della chiave hash per ogni inserimento richiede O (1). – Spike

2

Questo è in realtà un classico esempio di map reduce.

L'esempio nella pagina di wikipedia ti darà il conteggio delle parole di ogni parola univoca, ma puoi facilmente aggiungere un passaggio nel passaggio di riduzione che tiene traccia della parola corrente più comune (con un qualche tipo di mutex da affrontare problemi di concorrenza).

Se si dispone di un cluster distribuito di computer o di un computer altamente parallelizzato, verrà eseguito molto più rapidamente rispetto all'utilizzo della tabella hash.

0

Se si ha a che fare con un libro, si conosce il vocabolario e le frequenze di parola approssimative. Anche se non ti vengono fornite queste informazioni in anticipo, puoi ottenere un buon preventivo eseguendo la scansione di un campione casuale.

Per la risposta esatta, vorrei utilizzare una funzione di hash perfetta delle k più comuni parole. Una funzione di hash perfetta richiede memoria O (k) e garantisce una rapida ricerca O (1) nel caso peggiore.

Per le parole non comuni, utilizzerei una coda di priorità implementata come heap o albero di auto-bilanciamento. Un normale tavolo hash potrebbe anche essere una buona scelta.

Problemi correlati