web-dev-qa-db-fra.com

O(n) algorithme pour trouver la médiane d'une collection de nombres

Problème: l'entrée est une séquence (pas nécessairement triée) S = k1, k2, ..., kn de n nombres arbitraires. Considérons la collection C de n² nombres de la forme min {ki, kj}, pour 1 <= i, j <= n. Présenter un algorithme O(n) temps et O(n) espace pour trouver la médiane de C.

Jusqu'à présent, j'ai trouvé en examinant C pour différents ensembles S que le nombre d'instances du plus petit nombre dans S dans C est égal à (2n-1), le plus petit nombre suivant: (2n-3) et ainsi de suite jusqu'à ce que vous avoir qu'une seule instance du plus grand nombre.

Existe-t-il un moyen d'utiliser ces informations pour trouver la médiane de C?

39
ejf071189

Il existe plusieurs possibilités. Celui que j'aime est l'algorithme Select de Hoare. L'idée de base est similaire à un Quicksort, sauf que lorsque vous récursif, vous récursivement uniquement dans la partition qui contiendra le nombre (s) que vous recherchez.

Par exemple, si vous voulez la médiane de 100 nombres, vous devez commencer par partitionner le tableau, comme dans Quicksort. Vous obtiendriez deux partitions - dont l'une contient les 50e élément. Effectuez récursivement votre sélection dans cette partition. Continuez jusqu'à ce que votre partition ne contienne qu'un seul élément, qui sera la médiane (et notez que vous pouvez faire de même pour un autre élément de votre choix).

19
Jerry Coffin

Oui, bon puzzle. Nous pouvons trouver une médiane évoluant comme vous l'avez dit.

En C, nous avons 1 occurrence de max (k), 3 occurrences du suivant le plus élevé, 5 du suivant le plus élevé et ainsi de suite

  1. Si nous avons ordonné les éléments de C, le nombre d'éléments à gauche du mième nombre le plus élevé est m ^ 2 (somme des nombres impairs)

  2. Les nombres qui nous intéressent (pour calculer la médiane) a. Si n est impair est (n ^ 2 + 1)/2 = alpha b. Si n est pair alors alpha1 = n ^ 2/2 et alpha2 = n ^ 2/2 + 1 mais alpha1 = n ^ 2/2 n'est jamais un carré => le nombre immédiatement à droite de alpha1 est égal à alpha1 ( la somme des premiers nombres impairs est carrée) => alpha1 = alpha2.

  3. Il revient donc à déterminer m tel que m ^ 2 (somme des premiers m nombres impairs) est juste supérieur à (n ^ 2/2)

  4. Cela revient donc à déterminer m = plafond (n/sqrt (2) et mième nombre le plus élevé dans la séquence d'origine. (L'optimisation est de savoir si trouver mième plus haut ou (n-m-1) le plus bas).

  5. Nous pouvons facilement trouver le mième nombre le plus élevé (il suffit de noter le premier plus grand nombre à partir de la gauche) ou utiliser l'algorithme de médiane des médianes pour le faire en temps linéaire.

9
Om Deshmane

Wikipedia a un bon article sur Algorithmes de sélection . Si vous utilisez C++, la STL comprend un algorithme nth_element () avec un temps linéaire en moyenne.

6
Blastfurnace