简单二分代码死循环的原因

2,949 阅读2分钟

本人着实菜菜,今天好像领悟到了二分老写出死循环的原因。

题目:力扣704 二分查找

给定一个n个元素有序的(升序)整型数组nums 和一个目标值target,写一个函数搜索nums中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2 输出: -1 解释: 2 不存在 nums 中因此返回 -1

提示:

你可以假设 nums 中的所有元素是不重复的。n 将在 [1, 10000]之间。nums 的每个元素都将在 [-9999, 9999]之间。
代码1:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l = 0,r = nums.size()-1;
        while(l < r)
        {
            int mid = (l + r)/2;
            if(nums[mid]>target)
                r = mid-1;
            else
                l = mid;
        }
        
        if(nums[l]==target)
            return l;
        else
            return -1;
    }
};

代码2:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l = 0,r = nums.size()-1;
        while(l < r)
        {
            int mid = (l + r)/2;
            if(nums[mid]>=target)
                r = mid;
            else
                l = mid+1;
        }
        
        if(nums[l]==target)
            return l;
        else
            return -1;
    }
};

请问哪个代码会死循环?

答案是第二个喽。

为什么死循环呢?我的看法如下:
首先,我认为会不会死循环的关键就是l和r是否在每次循环后至少有一个的值发生了改变。
我们先看代码2,若进if语句,因为l \leq r,所以r会变小; 若进 else 语句, l 会变大。
再看代码1,若进入else语句,l就有可能不发生改变,所以就可能产生死循环。

所以,总结一下以后写二分的注意事项:

  1. 先根据二分的递进关系,写出一份有逻辑的代码。
  2. 再按照上述方法去检查是否会死循环。

希望以后简单二分不再稀里糊涂。