二分搜索详解

二分搜索详解

一、形式:

  • 第一种(左闭右闭形式)[l,r],这种每次搜索区间为 [m+1,r] 或 [l,m-1]

重点:当 l = r 时,区间为 [l, l],此时只有一个数,但仍要判断,因为二分搜索可能不存在这个值

l = 0,r = v.size()-1;
while(l <= r){ //终止条件  l = r + 1
int m = (l + r)/2
if(target == v[m]){
...
}else if(v[m] > target){
	r = m-1;
}else{
	l = m+1;
}
}
  • 第二种(左闭右开形式)[l,r), 这种每次搜索区间 [l,m) 或 [m+1,r)

重点,当 l = r 时,[l, l) 区间为空,即结束空间条件 l == r

l = 0,r = v.size();
while(l < r){ //终止条件  l = r
int m = (l+r)/2;
if(target == v[m]){
...
}else if(v[m] > target){
	r = m;
}else{
	l = m+1;
}
}

左右侧边界的值

[1, 2 , 2 , 2, 3 ,5]

  • 左侧边界即 1
l = 0, r = v.size();
while(l < r){
int m = (l + r )/2;
if(v[m] < target) // [ )形式最终 l == r,由于当 v[m] == target时 r = m,
//  则最后 l == r时 ,实际为l处的值,即第一个2位置1
	l = m + 1;
else 
	r = m;
}
return l;
  • 右侧边界
l = 0,r = v.size();
while(l < r){
int m = (l + r)/2;
if(v[m] <= target){// [,)形式,最终 l == r, 
//当 v[m] == m时,l = m+1,最后l == r时,实际为 r 处,即3的 位置 4
 l = m + 1;
}else{
	r = m;
}
}
return l-1;

二分搜索灵活运用

当二分查找有目标值时 f[m] 与 target 比较,当没有目标指时,通常与端点 l 或 r 比较。
为了:当进行一次比较时,一定能够确定答案在mid的某一侧。一次比较为 arr[mid]跟谁比的问题

有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

数据范围:1 \le n \le 100001≤n≤10000,数组中任意元素的值: 0 \le val \le 100000≤val≤10000
要求:空间复杂度:O(1)O(1) ,时间复杂度:O(logn)O(logn)

示例1
输入:
[3,4,5,1,2]

返回值:

1

示例2
输入:

[3,100,200,3]

返回值:

3

思路:数组是非降序数组,此题 比较右端点,旋转后 [l,k] 非降序 ,[k,r] 非降序

  • 当 f[m] < f[r] 时,说明 m 到 r 非降序,最小值在左边,r = m;
  • 当 f[m] == f[r] 时, r = r -1 ;缩小空间
  • 当 f[m] > f[r] 时,说明旋转了,最小值在 [l,m]内, l = m + 1;

假设比较左端点:

  • 当 f[m] < f[l] 时,说明 [m,r] 是非降序,最小值在 [l,m] 中,r = m;
  • 当 f[m] > f[l] 时, 说明 [l,m] 非降序 (可能没有旋转,可能旋转),结果 可能 在左边 可能在右边
class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int l = 0,r = rotateArray.size()-1;
        while(l < r){
            int m = l + (r - l)/2;
            if(rotateArray[m] > rotateArray[r]){
                l = m + 1;
            }else if(rotateArray[m] == rotateArray[r]){
                r = r-1;
            }else{
                r = m;
            }
            
        }
        return rotateArray[l];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值