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.log⁡k)


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.