边界二分查找

在这里插入图片描述

左边界的获取索引函数采用low<high,右边界的获取索引函数采用low<=high
具体思路见注释
注意:左边界获取索引要注意向右侧移动后越界
右边界获取索引要注意向左侧移动后越界
两种越界都是一直没找到target导致的
如果找到了第一个满足target的索引,则以此为据点(两种不同边界考虑的算法),找左边界往左移动,找右边界往右移动

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> range;
        range.push_back(searchLeft(nums,target));
        range.push_back(searchRight(nums,target));
        return range;
    }

    int searchLeft(vector<int> & nums, int target){
        if(nums.size()==0){
            return -1;
        }
        int high = nums.size();
        //左闭右开,0-nums.size()-1为有效索引,但是high取size()
        int low = 0;
        int mid = 0;
        while(low < high){
            //当nums[mid] >= target时high向左侧移动
            //左侧边界设定为mid,mid已经比较过,但要保持循环的左闭右开,所以high = mid 
            //直到low == high 时跳出循环 
            //此时high == low && nums[high] == nums[low] == nums[mid] == target
            //当nums[mid] < target时left向右侧移动,mid作为右半部分的左侧边界已经比较过
            //所以新左侧边界依然要保持左闭右开,为low = mid + 1
            //但是可能会出现越界的问题
            //当mid == high - 1 时,此时比较的nums[mid]为nums的最后一个值
            //如果他依然小于target,则low依然会加一,导致low==high,超出了nums的有效索引,此时虽然满足了跳出循环的条件,但是需要返回-1,代表一直到末尾依然没搜索到
            mid = low + ((high - low)>>2);//右移两位要加括号,相当于除以2
            if(nums[mid] == target){
                high = mid;
            }
            else if(nums[mid] < target){
                low = mid + 1;
            }
            else if(nums[mid] > target){
                high = mid;
            }
        }
        if(low == nums.size()){
            return -1;
            //搜索都最右侧,low越界依然没有找到
        }
        return nums[low]==target ? low : -1;
        //若low未越界,则如果它的值等于target,则找到左侧边界的index,否则没找到返回-1
    }
    int searchRight(vector<int> & nums, int target){
        if(nums.size()==0){
            return -1;
        }
        int high = nums.size()-1;
        //左闭右闭,0-nums.size()-1为有效索引
        int low = 0;
        int mid = 0;

        while(low <= high){
            mid = low +((high - low)>>2); 
            if(nums[mid] == target){
                low = mid + 1;
            }
            else if(nums[mid] < target){
                low = mid + 1;
            }
            else if(nums[mid] > target){
                high = mid - 1;
            }
        }
        //一直到最左侧high可能最后减一然后越界
        if(high < 0){
            return -1;
        }
        return nums[high]==target ? high : -1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值