二分查找

二分查找是很经典的算法了,写的时候虽然写对了,后面看了文章才知道细节还是蛮多的。
像target所在的区间,有[left,right]和[left,right)两种写法,会极大的影响边界处理条件。实质就在于我们需要在定义的区间内对target进行搜索,而不能有任何遗漏。后面的处理要和前面的区间范围配合。

逻辑还是简单的,根据书做一个总结,以[left,right]为例

  1. 首先确定搜索终止条件。这种区间定义时,需要考虑left==right,因此使用while(left<=right)(这其实就是在确定当left=right时也是区间定义的搜索空间,保证搜索空间的合法性)。同时定义right=nums.size()-1,这就保证了搜索空间都在定义区间中

  2. 后续处理边界时更新左右边界时使用left = mid + 1 和right = mid + 1,这一方面是因为原来的mid已经搜索过了,不需要重复搜索。同时因为是双闭区间的写法,也能保证后续的所有空间被搜索到。

而当[left,right)时

  1. 终止条件为left<right,同时right=nums.size(),保证不遗漏搜索
  2. 处理边界时,left = mid + 1不变,right需要修改为right = mid,这也是很显然的,虽然mid已经搜索过了,但是下一步的搜索空间是不包含right的,如果我们让right = mid - 1,就相当于忽略了这一个元素.
    最后给出代码
//[left,right],
//这里使用 vector<int>::size_type会在大小为1的数组上报错,同样去vscode上面也会报错,提示超出内存
//[left,right]
class Solution {
public:
    int search(vector<int>& nums, int target) {
           int left = 0, right = nums.size() - 1 ;
           while (left <= right ){
            int mid = (left + right) / 2;
            if (nums[mid] < target){
                left = mid + 1;
            } else if (nums[mid] > target ){
                right = mid - 1;     
            } else {
                return mid;
            } 
           }
        return -1;     
    }
};
//[left,right)
class Solution {
public:
    int search(vector<int>& nums, int target) {
           vector<int>::size_type left = 0, right = nums.size() ;
           while (left < right ){
             vector<int>::size_type mid = (left + right) / 2;
            if (nums[mid] < target){
                left = mid + 1;
            } else if (nums[mid] > target ){
                right = mid ;     
            } else {
                return mid;
            } 
           }
        return -1;     
    }
};
posted @ 2024-07-19 22:27  名字好难想zzz  阅读(22)  评论(0)    收藏  举报