Binaire de recherche pour trouver le point de rotation dans une zone de liste triée
J'ai une liste triée, qui est mis en rotation et voudraient faire une recherche binaire sur la liste pour trouver le minimum de l'élément.
Laisse supposer liste initiale est {1,2,3,4,5,6,7,8}
rotation de la liste peut être comme {5,6,7,8,1,2,3,4}
Normal binaire de recherche ne fonctionne pas dans ce cas. Une idée de comment faire cela.
-- Edit
J'ai une autre condition. Que faire si la liste n'est pas triée??
- Suis-je le seul qui, lorsqu'lit "liste" pense à une structure de données qui ne prend pas en charge l'accès aléatoire?
- même si vous n'êtes pas le seul, c'est encore une mauvaise conclusion à faire. En Java,
ArrayList<E> implements List<E>, RandomAccess
. D'autre part,LinkedList<E>
n'est pasRandomAccess
. - Juste comme je le pensais. Le problème avec java 🙂 Thx.
Vous devez vous connecter pour publier un commentaire.
Une légère modification sur le binaire de l'algorithme de recherche est tout ce dont vous avez besoin; voici la solution complète exécutable Java (voir Serg réponse pour Delphi mise en œuvre, et atg réponse pour une explication visuelle de l'algorithme).
Cette affiche:
Voir aussi
Integer[]
au lieu deint[]
>>> 1
au lieu de/2
Sur les doublons
Noter que les doublons fait qu'il est impossible de le faire dans
O(log N)
. Considérez les points suivants tableau de bits composé de nombreux1
, et un0
:Ce tableau peut être mis en rotation dans
N
façons, et la localisation de l'0
dansO(log N)
est impossible, car il n'y a aucun moyen de savoir si c'est dans le côté gauche ou droit de le "milieu".Alors, à moins que vous voulez trier d'abord et procéder à partir de là, vous devrez faire un linéaire de recherche pour trouver le minimum.
Voir aussi
(low + high) >>> 1;
avec(low + high - 1) >>> 1
? Il ignore les candidats plus rapidement. De plus, j'ai essayé de modifier ce code pour trouver le plus grand élément et dans ce cas(low + high + 1) >>> 1
est le seul bon choix. Voir mon sujet stackoverflow.com/questions/4844165/... pour plus de détails.Voici une image pour illustrer les algorithmes suggérés:
Je voudrais faire une recherche binaire sur la liste pour trouver le minimum de l'élément.
Ternaire, de recherche de travail pour ce cas: lorsque la fonction a exactement un minimum local.
http://en.wikipedia.org/wiki/Ternary_search
modifier
Lors de la deuxième lecture, j'ai probablement mal compris la question: la fonction n'est pas conforme exigences pour le ternaire de recherche :/Mais qui ne sont pas binaires de recherche de travail? Supposons, par ordre d'origine était en augmentation.
Il suffit de faire la la méthode de bissection sur
list - list[end]
sur l'intervalle [1, fin). La bissection de la méthode de recherche des zéros d'une fonction par la recherche d'un changement de signe, et fonctionne en O(log n).Par exemple,
{5,6,7,8,1,2,3,4} -> {1,2,3,4,-3,-2,-1,0}
Puis utilisez l' (discrétisé) méthode de bissection sur cette liste {1,2,3,4,-3,-2,-1}. Il sera de trouver un passage à zéro entre 4 et -3, ce qui correspond à votre point de rotation.
Delphi version du tiers amélioré (grâce à polygenelubricants code - encore un de plus la comparaison supprimé) variante:
Prendre une sous-suite
[i,j]
de la liste[first, last)
. Soit[i,j]
ne contient pas la discontinuité, dans ce cas*i <= *j
, ou elle ne l'est, auquel cas les éléments restants(j, last) U [first, i)
, sont correctement triés, auquel cas*j <= *i
.De manière récursive dédoublement le suspect jusqu'à ce que vous winnow à un seul élément. Prend O(log N) comparaisons.
Ma version binaire de l'algorithme de recherche mise en œuvre dans Java:
Code passé avec succès 5000 cas de tests, donc je pense qu'il est prêt pour la production.
La récursivité est très bonne, si nous voulons maintenir la simplicité et la lisibilité du code. Mais si on peut éviter de récursivité et de toujours conserver la lisibilité, il serait mieux parce que la récursivité des coûts est importante et n'est pas réellement évolutive.
Ici est une simple itératif méthode avec la logique à peu près comme discuté ci-dessus ( c'est profiter des binaires de recherche, l'ajout de petite partition logique).
Quelque chose comme ça pourrait fonctionner (Pas testé):
En C++ 11, ce problème peut être résolu avec partition_point: