Trova la mediana della matrice non ordinata in


45

Per trovare la mediana di un array non ordinato, possiamo creare un min-heap nel tempo per n elementi, quindi possiamo estrarre uno per uno n / 2 elementi per ottenere la mediana. Ma questo approccio richiederebbe tempo O ( n log n ) .O(nlogn)nn/2O(nlogn)

Possiamo fare lo stesso con un metodo in time? Se possiamo, allora come?O(n)



1
@JukkaSuomela Perché non rendere questa una risposta rapida e semplice (con una breve spiegazione di uno di questi algoritmi, idealmente)?
Raffaello

2
Nota la meta discussione relativa ; a quanto pare, semplici ricerche sul web portano alla risposta a questa domanda.
Raffaello

Risposte:


45

Questo è un caso speciale di un algoritmo di selezione che può trovare il ° elemento più piccolo di un array con k è la metà della dimensione dell'array. C'è un'implementazione che è lineare nel caso peggiore.kk

Algoritmo di selezione generico

Per prima cosa vediamo un algoritmo find-kthche trova il esimo elemento più piccolo di un array:k

find-kth(A, k)
  pivot = random element of A
  (L, R) = split(A, pivot)
  if k = |L|+1, return pivot
  if k ≤ |L|  , return find-kth(L, k)
  if k > |L|+1, return find-kth(R, k-(|L|+1))

La funzione split(A, pivot)restituisce in modo L,Rtale che tutti gli elementi in Rsiano maggiori di pivote Ltutti gli altri (meno un'occorrenza di pivot). Quindi tutto è fatto in modo ricorsivo.

O(n)O(n2)

Caso peggiore lineare: l' algoritmo mediana delle mediane

Un perno migliore è la mediana di tutte le mediane dei sotto array Adi dimensioni 5, usando la procedura chiamata sull'array di queste mediane.

find-kth(A, k)
  B = [median(A[1], .., A[5]), median(A[6], .., A[10]), ..]
  pivot = find-kth(B, |B|/2)
  ...

O(n)

Si noti che la maggior parte delle volte l'utilizzo di un perno casuale è più veloce.


Questa taglia è 5standard? Cosa succede se la dimensione di A è inferiore a 5?
Jayesh,

Per ogni n fisso, la complessità è costante, a meno che non sia infinita. Quindi, puoi usare qualsiasi algoritmo valido con complessità finita per questo caso speciale, anche se era O (2 ^ n). Per un n fisso (cioè al massimo 4 in out case), la complessità è al massimo O (2 ^ 4) = O (1).
v6ak,

3
Sul primo algoritmo: return A[k]non è corretto (a meno Ache non sia ordinato, il che renderebbe discutibile l'algoritmo). Se splitcapita di dividere in Amodo tale k = |L| + 1da non sapere ancora dove si trova l' kelemento th. Il caso base è quando |A| = 1è ancora necessario effettuare una delle due chiamate ricorsive.
wcochran,

2
@NickCaplinger corretto usando web.archive.org
jmad

1
Non è il caso peggiore per l'algoritmo di selezione generico O (NlogN)? Anche se la chiamata ricorsiva lascia solo il 10% dell'array dopo ogni chiamata, rimane comunque un logaritmo in base 10.
Ottaviano

6

n1/4O(n)

L'idea principale dell'algoritmo è utilizzare il campionamento. Dobbiamo trovare due elementi vicini nell'ordine della matrice e che abbiano la mediana tra loro. Vedere il riferimento [MU2017] per una discussione completa.


[MU2017] Michael Mitzenmacher ed Eli Upfal. "Probabilità e informatica: randomizzazione e tecniche probabilistiche in algoritmi e analisi dei dati", capitolo 3, pagine 57-62. Cambridge University Press, Seconda edizione, 2017.

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.