二分搜索模板

参考链接
花花酱哔哩哔哩视频

二分搜索的模板

正如bfs、dfs有模板,二分搜索也有模板。

模板一:左闭右开 [l,r)

public void bianrySearch(int l ,int r){
	while(l<r){
		int m = l+((r-l)>>1);
		if(f(m)) return m;//不一定有
		if(g(m)){
			r = m;//new range [l,m)
		}else{
			l = m+1;//new range [m+1,r)
		}
	}
	return l;//是g(m)成立的最小值
}

模板二:左闭右闭 [l,r]

public void bianrySearch(int l ,int r){
	while(l<=r){
		int m = l+((r-l)>>1);
		if(f(m)) return m;//不一定有
		if(g(m)){
			r = m-1;//new range [l,m)
		}else{
			l = m+1;//new range [m+1,r)
		}
	}
	return l;//是g(m)成立的最小值
}

对于左闭右开、左闭右闭,只是在细节上有些区别,最后结果是一样的。

g(x)是一个函数,g(x)满足 如果x>=m,g(x)>0为true;否则g(x)>0为false。
核心思想是:不要试图去找一个正确答案。试图去找一个分割点m,使得x>=m,g(x)>0为true。

在这里插入图片描述

对于不同类型的题目,核心工作就是寻找g(x)。

在我自己看来比较难理解的是最后求得的l是满足g(x)的最小值。我的理解是g(m)不满足条件,l=m+1,那l就是最可能的满足g(x)的最小值。即使在没有值满足g(x)的情况下,那l 会等于r或者r+1。

demo1 First Bad Version

278. First Bad Version
查找第一个是坏版本的版本号。这里g(x) = isBadVersion(x).
在这里插入图片描述

public int firstBadVersion(int n) {
    int l = 1,r = n;
    while(l<=r){
        int m = l+((r-l)>>1);           
        if(isBadVersion(m)){
            r = m-1;//new range [l,m)
        }else{
            l = m+1;//new range [m+1,r)
        }
    }
    return l;//是g(m)成立的最小值
}

demo2 my sqrt

my sqrt需要返回最大的一个数y,使得 y 2 < = x y^2<=x y2<=x
g ( y ) = y 2 − x > 0 g(y)=y^2-x>0 g(y)=y2x>0
在这里插入图片描述

public int mySqrt(int x) {
     if(x<2) return x;
     long l = 0,r = x>>1;
     long answer = l;
     while(l<=r){
         long middle = l+ ((r-l)>>1);
         if(middle*middle-x>0){
         	 r = middle - 1;           
         }else{
             l = middle+1;
         }
     }
     return (int)(l-1);
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值