Qual è il modo più veloce per trovare il valore Kth più piccolo in un elenco non ordinato senza ordinamento?


8

Il mio algoritmo iniziale:

  1. Confronta l'elemento 0 con ogni altro elemento, tenendo traccia di quanti elementi ne sono inferiori.
  2. Ripetere l'operazione per ciascun elemento fino a quando non viene trovato un elemento maggiore di esattamente (k-1).

Presumo che questo prenderebbe nel peggiore dei casi. È possibile ottenere un runtime più veloce senza ordinare l'elenco?O(n2)



Puoi creare un secondo elenco e ordinarlo? Vale a dire, puoi creare un elenco dei k valori più piccoli?
jmoreno,

Risposte:


10

Utilizza l'algoritmo di selezione per il tempo lineare https://en.m.wikipedia.org/wiki/Selection_algorithm


2
In particolare Median of Medians di Blum et al., 1973, risolve il problema di selezione nel tempo lineare peggiore. Probabilmente l'algoritmo più elegante che abbia mai visto.
quicksort,

6
Sebbene questo risponda alla domanda, è incoraggiato a fare la propria descrizione, non solo un collegamento.
Male

4

Purtroppo non posso limitarmi a commentare ma devo pubblicarlo come risposta.

Ad ogni modo, potresti provare a usare un min-heap sul tuo array non ordinato, dovresti essere in grado di ottenere una complessità temporale di O (n + k * logn).


3
Purtroppo non posso limitarmi a commentare ma devo pubblicarlo come risposta. - che è stata una buona cosa, poiché le risposte come il tuo post non appartengono ai commenti. I commenti servono per migliorare le domande, non per risposte brevi o simili.
Wrzlprmft,

1
Mh, mi sento come se la mia non fosse una risposta a tutti gli effetti ad essere onesti, non ho dato alcun dettaglio su perché o come l'uso di un heap minimo potrebbe ridurre la complessità del tempo, ecco perché mi è sembrato che appartenesse più in un commento che in una risposta
Luca Giorgi,

Dipende da se utilizzare min-heap o max-heap. k
Male

3

L'algoritmo Quickselect può farlo in una complessità media O (n), è uno degli algoritmi di selezione più usati secondo Wikipedia .

È derivato da QuickSort e come tale soffre di una complessità nel caso peggiore O (n²) se si utilizza un pivot errato (un problema che può essere evitato in pratica).

L'algoritmo in breve: dopo il pivot come in QuickSort, scendi solo nel lato inferiore o superiore dell'array, a seconda di quale di essi ha l'elemento che stai cercando.


2

Crea un heap massimo di dimensione . L'invariante è che l'heap contiene sempre i elementi più piccoli osservati finora.kk

  1. Inserisci i primi elementi dell'elenco nell'heapk
  2. Per ogni elemento rimanente nell'elenco: i
    • lascia che sia l'elemento massimo nell'heapM
    • Se , quindi eliminare e inserire nell'heapi<MMi

Alla fine, l'heap conterrà i elementi più piccoli nell'elenco.k

Cercare l'elemento massimo ha un costo costante. Il costo di inserimento e cancellazione è . La complessità temporale di questo metodo èO(k)O(n.logk)


1
Max-heap o Min-heap, dipende da k> n / 2.
Male

@Evil Vuoi verificare se sono più piccolo di uno qualsiasi degli elementi nell'heap. Quindi vuoi sapere se è più piccolo del più grande di loro. La ricerca dell'elemento massimo è O (1) in max-heap, ma non in min-heap.
Behrouz Babaki,

1
Vero. Immagina che k = 1 o k = n, useresti lo stesso heap in entrambi i casi? Forse è possibile utilizzare il min-heap in qualche modo quando è più veloce? (So ​​che lo è, hai +1 da me, solo un nitpick, non ti preoccupare).
Male

1
@Evil Hai ragione. Ho scartato in fretta il tuo commento. Quando k> n / 2, si può usare un metodo simile per memorizzare gli elementi (nk) più grandi in un heap min. Gli elementi rimossi dall'heap sono ciò che vogliamo.
Behrouz Babaki,
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.