遇到不严格有序的数组如何进行二分查找,

二分法的精辟干货文章

简单二分 只能针对有序数组
对下面数组无效,但局部有序
在这里插入图片描述
针对这个问题的模板
判断条件while (left < right)
模板1 寻找第一个满足XXX的位置:

int left = 0, right = nums.length - 1;
while (left < right) {
  int middle = left + (right - left) / 2;
  if (满足XXX) {
    right = middle;
  } else {
    left = middle + 1;
  }
}

模板2 寻找最后一个满足XXX的位置:

int left = 0, right = nums.length - 1;
while (left < right) {
  // +1是为了让相除结果向上取整,这个地方就是两套模板的区别之一
  int middle = left + (right - left + 1) / 2;
  if (满足XXX) {
    left = middle;
  } else {
    right = middle - 1;
  }
}

最终的二分结果,返回leftright 都可,因为退出循环时一定有 left==right

假设你只记住了 寻找第一个满足XXX 这个模板,但是遇到的实际需求是 寻找最后一个满足XXX ,你完全可以将二分目标修改为: 寻找第一个不满足XXX 的位置(也就是把 if条件 改成对应相反的,其余都不用动)。可知它的上一个位置就是 最后一个满足XXX 的,所以你把算出来的二分结果减去1,就是答案了。(反之同理,由 最后一个 -> 第一个 是 +1 操作

不过,这样得到的结果,很多时候都需要进行 后判断处理 ,否则会带来问题。

如果你是由 一种情况 转化到 另一种情况 的话,可能会带来 “索引越界” 的问题。这是因为:在结果转化时需要进行 -1(或者 +1) 的操作。假设本身的二分结果是0,然后你减去了1,结果变成-1了,那就下标越界啦!所以在最后返回前,必须判断一下这个下标究竟是否合法(如果题目保证一定存在答案,那么大可放心不必进行这些判断):

// 这里用 -1 表示下标非法时的返回结果
return left >= 0 && left < nums.length ? left : -1;

另外,如果题目不保证一定存在答案,那么即使没有产生 “索引越界” ,也可能得到 “错误答案” 。例如 寻找有序数组中元素值为 target 的元素所在位置,但是并不保证它一定存在 。拿到这题,我设定二分目标是: 寻找第一个满足 nums[i] >= target 的位置 i ,最终我得到的二分结果是 left (也同样是 right ) 。可是我只知道 nums[left] >= target 是没错的,但不见得 nums[left] == target 也一定没错!!因此就必须要后判断处理:

// 这里用 -1 表示数组中不存在 target 的返回结果
return nums[left] == target ? left : -1;

例题:
寻找旋转排序数组中的最小值
寻找峰值
寻找峰值答案:

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = (l + r) >> 1;
            if(nums[mid] >= nums[mid + 1])
            {
                r = mid;
            }
            else 
            {
                l = mid + 1;
            }
        }
        return l;
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值