Trova la mediana di un elenco di array ordinati


8

Input: una serie di matrici (di numeri). Gli elementi all'interno di ciascun array sono ordinati, ma l'insieme di array non è necessariamente ordinato. Le matrici non hanno necessariamente le stesse dimensioni. Il numero totale di elementi è .Ai
n

Output: il esimo elemento più piccolo tra tutti gli elementi nell'input.k

Qual è l'algoritmo più efficiente per questo problema?

È possibile, ad esempio, ottenere un tempo di esecuzione di ?O(+logn)


C'è una domanda strettamente correlata su SO , con risposte insoddisfacenti.
Joe,

Tutti gli array sono della stessa lunghezza?
vonbrand,

Le matrici non hanno necessariamente le stesse dimensioni. Tuttavia, sono anche interessato a un caso speciale in cui le dimensioni sono geometriche, ovvero arrayUNio ha dimensioni n/2io, ma dubito che aiuterà nel tempo di esecuzione.
Joe,

4
Come si ottiene O(logn)? Puoi prendereO((logn)2)emulando l'algoritmo "quickselect". In ogni fase, scegli un perno e calcola quanti elementi ci sono sotto, inO(logn). Quindi rimuovi gli elementi dalla parte sbagliata e ripeti. Il processo termina dopologniterazioni (nell'aspettativa, o nel peggiore dei casi se si sceglie il perno in modo intelligente).
Yuval Filmus,

2
@Joe Penso che dovresti descrivere anche il tuo algoritmo. Sarebbe molto interessante e potrebbe fornire un punto di partenza per algoritmi migliori se corretti. Se errato, le persone potrebbero essere in grado di trovare eventuali errori.
Paresh,

Risposte:


5

Puoi farlo dentro O(l+k log l) tempo e O(l) spazio extra come segue:

  1. Costruisci un heap binario con una voce per ciascuno degli array. La chiave per l'ingressoio è l'elemento più piccolo nell'array Aio. Questo richiedeO(l) tempo.
  2. Seleziona la voce più piccola dall'heap e rimuovila (prendendo O(log l) tempo). Aggiungi quella voce all'heap usando come chiave la chiave successiva più piccola nell'array pertinenteO(log l) tempo).
  3. Fai il passaggio precedente Kvolte. L'ultimo elemento che rimuovi dall'heap è la tua risposta.

Se sostituisci l'heap binario con un heap di Fibonacci, penso che questo ti riduca all'ammortamento O(l+K) tempo, ma in pratica sarà più lento dell'heap binario a meno che l è enorme.

Ho il sospetto che il limite di heap di Fibonacci sia ottimale, perché intuitivamente dovrai ispezionare almeno K elementi per trovare il file Kil più piccolo, e dovrai ispezionare almeno un elemento da ciascuno dei l array poiché non sai come sono ordinati, il che dà immediatamente un limite inferiore di Ω(max(K,l))=Ω(K+l).


3
Non devi ispezionare almeno Kelementi poiché le matrici sono ordinate. Vedi la soluzione nel mio commento, che dàO((logn)2).
Yuval Filmus,

1
È possibile migliorare il tempo di esecuzione del caso peggiore nel modello RAM, poiché è possibile implementare la coda di priorità per n elementi in o(logn). In questo modello, è possibile ottenere entrambe le operazioni di inserimento ed eliminazioneO(loglogn) e O(1)tempo per l'operazione findMin.
Massimo Cafaro,

1
Sei sicuro che l'heap di Fibonnaci supporti l'operazione corretta? Penso che stai pensando di diminuire la chiave in un min-heap.
Joe,

Questo è fondamentalmente lo stesso della risposta di vonbrand, con l'aggiunta dell'osservazione che non devi unire alcun elemento dopo il kth.
Joe

Credo che l'heap di Fibonacci ti permetta di diminuire o aumentare una chiave O(1)tempo. Sì, questa è sostanzialmente la stessa risposta, ma osservando che devi solo unireKelements riduce il tempo di esecuzione in modo corretto.
Matt Lewis,

5

Ecco un randomizzato O(log2n)algoritmo. Probabilmente può essere derandomizzato usando lo stesso trucco usato per derandomizzare la solita selezione rapida.

Emuliamo il classico algoritmo di selezione rapida. In ogni fase, scegli un perno e calcola quanti elementi ci sono sotto, inO(logn), utilizzando la ricerca binaria in ciascun elenco. Quindi rimuovi gli elementi dalla parte sbagliata e ripeti. Il processo termina dopologn iterazioni in attesa.


1

Ciò sembra essere risolto dal documento Selezione e classificazione generalizzate (versione preliminare) di Frederickson e Johnson in STOC '80.

Danno limiti superiori e inferiori di: Θ(+Σio=1log|UNio|) che risulta essere logn per la maggior parte delle distribuzioni di dimensioni di array.

L'attuale algoritmo per raggiungere il limite superiore è apparentemente riportato in un precedente documento: Algoritmi ottimali per la generazione di informazioni quantili in X + Y e matrici con colonne ordinate , Proc. 13ª Conferenza annuale su Scienza e sistemi dell'informazione, The Johns Hopkins University (1979) 47-52.


0

Un -way merge richiede tempo Θ(nlog) (utilizzare un modo efficiente per rappresentare una coda prioritaria degli elementi head in ciascun elenco), quindi selezionare K-th elemento in tempo costante. Penso che questo sia discusso in "Ordinamento e ricerca" di Knuth per l'ordinamento. Ottenere il più piccolo (o il più grande) richiede chiaramenteΘ(), per un array non ordinato lo è O(n) IIRC.

Descrivi il tuo algoritmo.


1
Questo è molto più lento di quello che mi interessa. Puoi trovare la mediana O(n)tempo semplicemente concatenando le liste e usando l'algoritmo di selezione temporale lineare.
Joe,
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.