Trouver le k plus petit élément d'une séquence donnée uniquement avec O (k) mémoire O (n) temps

11

Supposons que nous lisions une séquence de n nombres, un par un. Comment trouver le k plus petit élément simplement en utilisant la mémoire de cellule O(k) et en temps linéaire ( O(n) ). Je pense que nous devrions enregistrer les premiers ktermes de la séquence et lorsque nous obtenons le k+1 'ème terme, supprimer un terme qui nous assure qu'il ne peut pas être le k ième élément le plus petit, puis enregistrer k+1 ' ème terme. Nous devrions donc avoir un indicateur qui montre ce terme inutilisable à chaque étape et cet indicateur devrait être mis à jour à chaque étape rapidement. J'ai commencé avec "max"; mais il ne peut pas se mettre à jour rapidement; Signifie que si nous considérons max, alors lors de la première suppression, nous manquons le max et nous devons rechercher max dans O(k) et sa cause (nk)×O(k) temps qu'il n'est pas linéaire. Peut-être devrions-nous enregistrer les premiers ktermes de la séquence de manière plus intelligente.

Comment puis-je résoudre ce problème?

Shahab_HK
la source
1
Êtes-vous intéressé par un algorithme en ligne, ou un algorithme le ferait-il?
Yuval Filmus
Si k=θ(n) vous pouvez le faire en utilisant un algorithme de statistiques d'ordre. Si k=o(n) vous pouvez le faire O(k) mémoire et O(nlogk) utilisant n'importe quel arbre à hauteur équilibrée.
Shreesh
Cela s'appelle le problème de sélection en.wikipedia.org/wiki/Selection_algorithm
xavierm02
Il existe des algorithmes linéaires sur place, que vous pouvez rechercher sur Google, mais ils sont quelque peu compliqués.
Yuval Filmus
@ xavierm02 ce n'est pas le problème de sélection à l'identique. Parce qu'il y a une contrainte de limite de mémoire.
Shahab_HK

Réponses:

16

Créez un tampon de taille . Lire 2 k éléments du tableau. Utilisez un algorithme de sélection à temps linéaire pour partitionner le tampon de sorte que les k plus petits éléments soient les premiers; cela prend du temps O ( k ) . Maintenant, lisez dans un autre k éléments de votre tableau dans le tampon, en remplaçant les k plus grands éléments du tampon, partitionnez le tampon comme précédemment et répétez.2k2kkO(k)kk

Cela prend temps et O ( k ) espace.O(kn/k)=O(n)O(k)

jbapple
la source
+1, cela correspond aux asymptotiques demandées. Cela étant dit, je ne pense pas que ce soit plus rapide que de faire un seul algorithme de sélection en temps linéaire ... sauf lorsque est une petite constante, cela fournit une perspective intéressante. Par exemple, pour k = 1, cet algorithme produit la fonction. kk=1min
orlp
1
Parfois, l'algorithme de sélection linéaire-temps utilise trop d'espace. Par exemple, il ne convient pas pour une utilisation dans un contexte de streaming ou lorsque le tableau d'entrée est immuable.
jbapple
Ce sont des points valables.
orlp
3

O(k)O(nlogk)kO(k)O(logk)O(k+nlogk)O(nlogk)

O(logn)O(n)kk

O(logn)O(k)O(logn)264log264=64kn

orlp
la source
O(n×logmin(k,nk))
@ xavierm02 = . Preuve: le pire des cas pour est . Le pire des cas pour est . Ils sont les mêmes à l'intérieur d'un facteur constant, donc = . O(min(k,nk))O(k)knmin(k,nk)n2O(min(k,nk))O(k)
orlp
@ xavierm02 Cela étant dit, c'est toujours une belle accélération :)
orlp
un,k=k est mais ce n'est pas . Supposons que ce soit le cas. Ensuite, il y a du et du sorte que pour chaque , nous avons , ce qui est clairement faux (car nous pouvons prendre Donc . O(k)O(min(k,nk))CMMknkC(nk)n=k+).O(min(k,nk))O(k)
xavierm02
@ xavierm02 Je ne connais pas votre notation . Pour être juste, je ne suis généralement pas assez familier avec la notation multidimensionnelle big- , surtout si l'on considère que les dimensions ne sont pas indépendantes. un,kOn,k
orlp