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

    技术2025-11-27  15

    关于二分查找的理解

    在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. 二分查找

    Processed: 0.020, SQL: 9