J'essaie de trouver quelque chose à résoudre:
Étant donné un tas-max représenté sous forme de tableau, retourne le kème élément le plus grand sans modifier le tas. On m'a demandé de le faire en temps linéaire, mais on m'a dit que cela pouvait être fait en un temps record.
J'ai pensé à une solution:
Utilisez un deuxième tas-max et remplissez-le avec k ou k + 1 valeurs dans celui-ci (largeur d'abord traversée dans celle d'origine), puis pop k éléments et obtenez celui désiré. Je suppose que cela devrait être O (N + logN) = O (N)
Existe-t-il une meilleure solution, peut-être dans O(logN)?
Le max-heap peut avoir plusieurs manières, un meilleur cas est un tableau complet trié, et dans d'autres cas extrêmement, le heap peut avoir une structure totalement asymétrique.
Ici peut voir ceci:
Dans le premier cas, le kième élément lagest est à la kième position, vous pouvez calculer avec O(1) avec une représentation sous forme de tableau de tas . Mais, en général, vous aurez besoin de vérifier entre ( k, 2k) et triez-les (ou triez partiellement avec un autre segment). Pour autant que je sache, c'est O (K · log (k))
Et l'algorithme:
Input:
Integer kth <- 8
Heap heap <- {19,18,10,17,14,9,4,16,15,13,12}
BEGIN
Heap positionHeap <- Heap with comparation: ((n0,n1)->compare(heap[n1], heap[n0]))
Integer childPosition
Integer candidatePosition <- 0
Integer count <- 0
positionHeap.Push(candidate)
WHILE (count < kth) DO
candidatePosition <- positionHeap.pop();
childPosition <- candidatePosition * 2 + 1
IF (childPosition < size(heap)) THEN
positionHeap.Push(childPosition)
childPosition <- childPosition + 1
IF (childPosition < size(heap)) THEN
positionHeap.Push(childPosition)
END-IF
END-IF
count <- count + 1
END-WHILE
print heap[candidate]
END-BEGIN
ÉDITÉ
J'ai trouvé "L'algorithme optimal de sélection dans un min-tas" de Frederickson ici: ftp://paranoidbits.com/ebooks/An%20Optimal%20Algorithm%20for%20Selection%20in%20a%20Min-Heap. pdf
Non, il n'y a pas d'algorithme O (log n) -time, par une simple limite inférieure de sonde de cellule. Supposons que k soit une puissance de deux (sans perte de généralité) et que le tas ressemble à (min-heap entrant car il est plus facile de marquer, mais il n'y a pas de réelle différence)
1
2 3
4 5 6 7
.............
permutation of [k, 2k).
Dans le pire des cas, nous devons lire l'intégralité de la permutation car il n'y a pas de relation d'ordre imposée par le tas, et tant que k n'est pas trouvé, il pourrait se trouver dans un endroit non encore examiné. Cela prend du temps Omega (k), correspondant à l'algorithme (compliqué!) Posté par templatetypedef.
À ma connaissance, il n’existe pas d’algorithme simple permettant de résoudre ce problème. Le meilleur algorithme que je connaisse est dû à Frederickson et ce n'est pas facile. Vous pouvez consulter le document ici, mais il se peut que ce soit derrière un paywall. Il s'exécute dans le temps O(k) et ceci est prétendu être le meilleur temps possible. Je suppose donc qu'une solution log-time n'existe pas.
Si je trouve un meilleur algorithme que celui-ci, je vous le ferai savoir.
J'espère que cela t'aides!
Max-heap dans un tableau: element at i is larger than elements at 2*i+1 and 2*i+2
(i
est basé sur 0)
Vous aurez besoin d'un autre segment de mémoire maximal (insert
, pop
, empty
) avec des paires d'éléments (value, index)
triés par value
. Pseudocode (sans vérification des limites):
input: k
1. insert (at(0), 0)
2. (v, i) <- pop and k <- k - 1
3. if k == 0 return v
4. insert (at(2*i+1), 2*i+1) and insert (at(2*+2), 2*+2)
5. goto 2
Évaluation du temps d'exécution