1
votes

Recherche binaire lorsque la condition de fin est `gauche

Je lisais le Modèle de recherche binaire II dans leetcode :

Il est utilisé pour rechercher un élément ou une condition qui nécessite d'accéder à l'index courant et à l'index de son voisin droit immédiat dans le tableau.

In [4]: nums = list(range(100))             

In [5]: binarySearch(nums, 55)              
Out[5]: 55

In [6]: binarySearch(nums, 101)             
Out[6]: -1

In [7]: binarySearch(nums, 38)              
Out[7]: 38

Il me semble que la condition supplémentaire et nums [left] == ​​target n'est pas nécessaire.

Lors du changement:

def binarySearch(nums, target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    if len(nums) == 0:
        return -1

    left, right = 0, len(nums)
    while left < right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid

    # Post-processing:
    # End Condition: left == right
    if left != len(nums):
        return left
    return -1

à seulement:

if left != len(nums):

... cela fonctionne parfaitement:

if left != len(nums) and nums[left] == target:

Tests:

def binarySearch(nums, target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    if len(nums) == 0:
        return -1

    left, right = 0, len(nums)
    while left < right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid

    # Post-processing:
    # End Condition: left == right
    if left != len(nums) and nums[left] == target:
        return left
    return -1

Quelle est la raison pour laquelle nums [left] == ​​target devrait être ajouté?

Le résumé du Leetcode sur le modèle (pour référence si vous ne pouviez pas ouvrir son lien):

Attributs clés:

  • Une manière avancée de mettre en œuvre la recherche binaire.
  • La condition de recherche doit accéder au voisin droit immédiat de l'élément
  • Utilisez le voisin droit de l'élément pour déterminer si la condition est remplie et décider s'il faut aller à gauche ou à droite
  • Gurantees [sic] L'espace de recherche est d'au moins 2 à chaque étape
  • Post-traitement requis. La boucle / récursivité se termine lorsqu'il vous reste 1 élément. Il faut évaluer si l'élément restant répond aux condition.

Syntaxe distinctive:

  • Condition initiale: left = 0, right = length
  • Résiliation: left == right
  • Recherche à gauche: right = mid
  • Recherche à droite: gauche = milieu + 1


4 commentaires

Test avec nums = [9] et binarySearch (nums, 2) . Vous avez besoin de la dernière condition pour vous assurer que vous avez réellement trouvé l'élément cible.


Cela fonctionne In [19]: binarySearch (list (range (10)), 2) Out [19]: 2 In [20]: binarySearch (list (range (9)), 2) Out [20]: 2 @ChrisHappy


Désolé, la liste ne doit pas être 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 . Ce devrait être simplement 9 . Reformulé, l'algorithme binary_search échoue lorsque l'élément n'est pas dans le tableau et il n'est pas plus grand que le plus grand élément et pas plus petit que le plus petit élément.


Donc, pourrait être simplement supprimer la ligne `if left! = Len (nums) and nums [left] == ​​target:`


3 Réponses :


0
votes

Test avec nums = [9] et binarySearch (nums, 2) . Si je comprends bien le code, binary_search renverra 0 comme "index" de l'élément trouvé.

Vous avez besoin de la dernière condition pour vous assurer que vous a effectivement trouvé l'élément cible .

Sinon, vous cherchez simplement un index pour l'élément le plus proche de la cible dans le tableau.

Encore un exemple: p>

IN nums = [1, 3, 4]

IN binary_search(nums, 2)
OUT 2 /* When 2 isn't in the array */


1 commentaires

l'exemple ne peut pas être une indication formelle de la nécessité de ce contrôle (et en particulier de cette chose "à peu près")



2
votes

Contrairement à la version canonique de la recherche binaire où la boucle se termine dès que lo> hi est rencontré, dans ce cas, la boucle se termine lorsque lo == hi . Mais comme l'élément nums [lo] (qui est aussi nums [hi] ) doit également être inspecté, la vérification supplémentaire est ajoutée après la boucle.

Il est garanti que la boucle se termine uniquement et uniquement lorsque lo == hi , car le déplacement vers la gauche inclut l'élément mid dans la recherche future ( else: right = mid ) en version canonique, l'élément mid est exclu de la recherche future dans les deux cas


0 commentaires

0
votes

Tout d'abord, lorsque vous changez si à gauche! = len (nums) et nums [left] == ​​target: en si left! = len (nums): cela semble fonctionner correctement car vos tests sont effectués avec nums = list (range (100)) qui génère la séquence d'entiers 0, 1, 2,. .., 99 , en tant que tel, chaque index de nums est le même que son élément, c'est-à-dire nums [i] == i . Sans nums [left] == ​​target , vous retournez en fait l'index le plus proche de l'index de votre élément target , et puisque avec votre test chaque index coïncide avec son élément alors il semble donner des résultats corrects, mais c'est faux . La nums [left] == ​​target est la condition de fin qui garantit que vous avez effectivement trouvé votre élément target dans nums .


0 commentaires