[数据结构与算法]关于二分查找的理解

关于二分查找的理解

leetcode_35搜索插入的位置这道题中,liweiwei大佬详细的介绍了二分查找最关键的一个问题,就是如何避免陷入死循环。在此我根据大佬的笔记,总结一下自己的理解。

首先来看题目:

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。
输入: [1,3,5,6], 5
输出: 2

正常的解法如下:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int size = nums.size();
        if (size == 0) {
            return 0;
        }
        // 特判
        if (nums[size - 1] < target) {
            return size;
        }
        int left = 0;
        int right = size - 1;
        while (left < right) {
            // int mid = left + (right - left + 1)/2;//右中位数
           int mid = left + (right-left)/2; //左中位数
            if (nums[mid] < target) {
                left = mid + 1;
            }
            else if (nums[mid] == target) {
                return mid;
            }
            else {
                right = mid;
            }
        }
        return left; 
    }
};

这道题目的重点在与 左右区间的如何划分,这个地方如何理解呢?

正如二分法所要求的mid,当求得mid,之后,根据mid的值和目标值进行比较,会存在区间的划分的两种情况:

  • 情况1:

    [left,mid][mid+1,right]

  • 情况2:

    [left,mid-1][mid,right]

但是mid的值怎么计算呢?这个地方有两个需要注意的点!

注意点1:如何防止溢出

正常对于mid的计算我们都是:

int mid = (left+right)/2;

这种情况下,当数组很长的时候,两个数直接相加就可能溢出。

所以一种比较好的习惯是:

int mid = left + (right-left)/2;

注意点2:mid值是上取整还是下取整?

假设我们最后剩下的搜索区间是[2,3],那么因为int向下取整的原因,用注意点1里的方法,mid的值就是2;

如果是下取整,那么会存在什么情况呢?

我们分别代入区间划分的两种情况下进行测试:

  • 情况1:

    int mid = 2;
    //判断1:此时right=mid
    [left,mid] = [2,2]
    //判断2:left=mid+1
    [mid+1,right] = [3,3]
    

    没什么问题.

    return left!

  • 情况2:

    int mid = 2;
    //判断1:此时right=mid-1
    [left,mid-1] = [2,1]
    //判断2:left=mid
    [mid,right] = [2,3] //陷入死循环!!!
    

    在判断1的情况下明显出错了!区间都划分的不对了。或者出现 死循环!

如果我们使用的是上取整呢?

也就是这样:

int mid = left + (right-left+1)/2;

再次分别代入以下区间划分的情况下进行测试:

  • 情况1:

    int mid = 3;
    //判断1:此时right=mid
    [left,mid] = [2,3]//陷入死循环!!!
    //判断2:left=mid+1
    [mid+1,right] = [4,3]//区间不对了!!!
    

    出现错误!不是陷入死循环,就是区间判断错误!不知道该如何退出!

  • 情况2:

    int mid = 3;
    //判断1:此时right=mid-1
    [left,mid-1] = [2,2]
    //判断2:left=mid
    [mid,right] = [3,3]
    

    这种情况下安全退出!

所以这就是大佬说的,当遇到left = mid的时候,才需要调整为上取整!!!!

相似的练习题!

704. 二分查找

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章