Comment trouver le max. et min. dans le tableau à l'aide de minimum de comparaisons?
C'est une question d'entrevue: étant donné un tableau d'entiers de trouver le max. et min. utiliser le minimum de comparaisons.
Évidemment, je peux en boucle sur le tableau à deux reprises et l'utilisation ~2n
des comparaisons dans le pire des cas, mais j'aimerais faire mieux.
- Eh bien, je peux imaginer des algorithmes nécessitant pas de comparaisons à tous (par exemple le comptage de tri, puis choisissez le premier et le dernier élément). Mais je ne pense pas que c'est le point.
- Juste par curiosité, que les entreprises poser de telles questions? J'ai été interviewé par de nombreuses entreprises, mais je n'ai jamais vu de toute question de ce genre.
- C'était un Israélien de démarrage.
Vous devez vous connecter pour publier un commentaire.
De cette façon que vous feriez 3 comparaisons de 2 éléments, s'élevant à
3N/2
total des comparaisons pourN
éléments.3N/2 - 2
puisque nous n'avons pas besoin de mettre à jour min ou max dans la première étape?S'efforcent d'améliorer la réponse par srbh.kmr. Disons que nous avons la séquence:
Comparer
a1
&a2
et calculermin12
,max12
:De même calculer
min34
,max34
. Depuisa5
est seul, la garder comme elle est...Maintenant comparer
min12
&min34
et calculermin14
, de même calculermax14
. Enfin comparermin14
&a5
pour calculermin15
. De même calculermax15
.Au total, il est à seulement 6 comparaisons!
Cette solution peut être étendue à un tableau de longueur arbitraire. Probablement peut être mis en œuvre par une approche similaire à la fusion-tri (briser le tableau en deux et calculer
min
max
pour chaque semestre).Mise à JOUR: Voici le récursive de code en C:
Maintenant, je ne peut pas indiquer le nombre exact de comparaisons en termes de
N
(le nombre d'éléments dans le tableau). Mais il est difficile de voir comment on peut aller en dessous de ce nombre de comparaisons.Mise à JOUR: On peut calculer le nombre de comparaisons comme ci-dessous:
Au bas de cet arbre de calculs, nous former des paires de nombres entiers du tableau d'origine. Nous avons donc
N /2
nœuds feuilles. Pour chacun de ces nœuds feuilles nous faisons exactement 1 comparaison.En se référant aux propriétés d'un parfait-binaire-tree, nous avons:
Pour chaque noeud interne nous n'2 comparaisons. Par conséquent, nous avons
N - 2
comparaisons. Avec leN /2
des comparaisons sur les noeuds terminaux, nous avons(3N /2) - 2
total des comparaisons.Donc, peut-être que c'est la solution srbh.kmr implicite dans sa réponse.
3N/2-2
ou3N/2-3/2
selon pair/impair N. Vous pourriez économiser encore plus la récursivité de l'espace, si vous allez pour une analyse linéaire de bien 😉n
peut être bizarre ou le nombre de paires peut être bizarre. Avec votre récursive de la mise en œuvre, cela pourrait entraîner plus de(3n/2)-2
comparaisons, car vous frapper de la base de cas, plus souvent qui exigent davantage de comparaisons.aller pour diviser et conquérir !
1,3,2,5
pour cette découverte min,max va prendre 6 comparaisons
mais les diviser
maintenant, nous pouvons comparer les deux minutes et maxs
donc un total de quatre comparaisons pour trouver à la fois des min et max.
Une approche un peu différente, qui utilise l'arithmétique des nombres entiers au lieu de comparaisons (ce qui n'est pas explicitement interdit)
Force Brute est plus RAPIDE!
J'aimerais quelqu'un pour me montrer l'erreur de mes moyens, ici, mais, ...
J'ai comparé les temps d'exécution de la force brute méthode contre le (beau) récursive diviser et conquérir. Résultats typiques (en 10 000 000 d'appels pour chaque fonction):
Étonnamment, la force brute de la méthode était d'environ 2,9 fois plus rapide pour un tableau de 10 éléments, et 3,4 fois plus rapide pour un tableau de 1 000 000 d'articles.
De toute évidence, le nombre de comparaisons est pas le problème, mais peut-être le nombre de ré-affectations, et la surcharge de l'appel d'une fonction récursive (ce qui pourrait expliquer pourquoi 1 000 000 de valeurs plus lent que les 10 valeurs).
Mises en garde : je l'ai fait en VBA, C, et j'ai été en comparant les nombres de double précision et le retour de l'index dans le tableau des valeurs Min et Max.
Voici le code que j'ai utilisé (classe cPerformanceCounter n'est pas inclus ici, mais utilise QueryPerformanceCounter haute résolution pour le timing) :
Après la lecture de la question et les réponses, j'ai décidé d'essayer un peu de versions (en C#).
Je pensais que le plus rapide serait Anton Knyazyev est l'un (direction gratuit),
il n'est pas (ma boite).
Résultats:
Pourquoi minmax1 et minmax3 plus vite?
Probablement parce que la branche "prédicteur" elle fait du bon travail,
chaque itération de la chance, une nouvelle min (ou max) est trouvé, diminue,
si les prédictions de devenir meilleur.
Dans l'ensemble c'est un test simple. Je me rends compte que mes conclusions peuvent être:
-prématuré.
-non valable pour les différentes plates-formes.
Disons qu'ils sont donnés à titre indicatif.
Edit: Break-even point de minmax0, minmax3: ~100 éléments,
10 000 éléments: minmax3 ~3,5 fois plus rapide que minmax0.
Un simple pseudo code de l'algorithme récursif:
2n
méthode de comparaison, l'OP est à la recherche de solutions avec moins de temps d'exécution asymptotique.Mon divide & conquer approche avec java jusqu'à présent:
//cela peut être fait en log(n) la complexité!!!
Juste une boucle sur le tableau une fois, garder la trace de max et min jusqu'à présent.