二分搜索模板

參考鏈接
花花醬嗶哩嗶哩視頻

二分搜索的模板

正如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,使得y2<=xy^2<=x
g(y)=y2x>=0g(y)=y^2-x>=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;
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章