二分算法(错的次数多了,感觉还是有必要建一个文章)

本文章针对对于二分算法有一定基础但是并不算牢固的童鞋(譬如我)

二分的注意事项

做的题多了,发现怎么用二分的都有,有在判断条件上用left<=right的,也有用left<right的,有在mid<target的时候让left=mid也有让left=mid+1的,(此处数列递增排序),同理right的改变也是五花八门,最终二分结束到底得出个啥来,会产生什么问题我经常弄得很懵,今天先把这个基础的搞熟。

基础二分模板

这个模板应用于寻找x在数组中的位置(如果有的话)如果没有的话,就寻找在数组中第一个比x大的元素的位置。返回的是left,它能满足这个要求。

int bin_search(int *a,int n,int x){
    //此处针对左开右闭的数组
    int left=0,right=n;//其中left是数组第一个元素位置
    //right是最后一个元素的后面一个位置
    while(left<right){//判断条件是left!=right
        int mid=(left+right)>>1;
        if(a[mid]>x){
            right=mid;//right直接等于mid
        }else left=mid+1;//left等于mid+1
    }
    return left;//最后得到的left是对应x在数组中的位置或者
    //第一个比x大的元素的位置
}

对这个模板的理解:

它一开始的二分由left与right组成的区间是左开右闭的,所以接下来每一次更新出来的区间都是左开右闭的,因此才有right是直接等于mid但是left是等于mid+1,同理,因为左开右闭,所以left肯定不能等于right/
唔,还有锁定目标的原理,就是因为利用了计算机除法中小数直接舍弃,在形状上表现出来的就是两个相邻的数字比如3和5如果target是4经过二分之后肯定结果是mid+1返回5的位置,因此是如果没有x的话会返回第一个比x大的位置。
举一反三:如下代码

Fangio同学常用二分模板

bool judge(int a,int x){
	return x>a;
}
bool Judge(int a,int x){
	return a==x;
}
//要返回x在数组中的位置
//(如果没有的话)就返回第一个比x小的数的位置
int Bin_search(vector<int> &arr,int x,int n){
//默认arr数组是排序好了升序排列
//而且下标为0的位置不存储目标元素,也就是说l和r的起始位置都不在目标数组内部)
	int l=0,r=n,mid;	
	while(l+1<r){
		mid=(l+r)>>1;
		if(Judge(arr[mid],x)){
			return mid;
		}
		else if(judge(arr[mid],x)){
			l=mid;
		}else r=mid;
	}
//如果要返回第一个比x小的位置的话就返回l
//如果返回第一个比x大的数的位置的话就返回r
	return r;
}

个人觉得好理解且好用,把所有比target小的元素是红色,大的是灰色,然后每次mid不符合要求的时候要么把他归入到红色区,要么归入灰色区,如此下来,最后把所有元素涂上颜色,那么l和r就分别指向了红色区最右侧以及最左侧,返回第一个比x小的位置的话就返回l,反之,如果返回第一个比x大的数的位置的话就返回r
好处如下:

  1. 对于不同的题判断条件不变,只需要改变Judge函数
  2. 对于不同的题,while后面括号里的东西不变,保持l+1<r
  3. 对于不同的题,不需要考虑mid用不用+1,只管l=mid或者r=mid
  4. 只改变return的值就可以改变返回较小还是较大

拓展模板

我想返回x在数组中的位置或者是第一个比x小的位置

见过的其他二分应用

int l = 1, r = len, pos = 0; 
                while (l <= r) {
                    int mid = (l + r) >> 1;
                    if (d[mid] < nums[i]) 
                    {//此处nums[i]是target
                        pos = mid;
                        l = mid + 1;
                    } else {
                        r = mid - 1;
                    }
                }
                d[pos + 1] = nums[i];
            }

作者:力扣官方题解
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

此题链接,只不过这道题还考察了dp,那部分我就不说了
然后,如果遇到了还有其他的我再去发

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值