二分法之通用模板


在這里我們一共有兩個模板

模板1

我們將區間[l,r]划分為[l,mid]和[mid+1,r]時,其更新操作是r=mid或者l=mid+1;計算mid時不用加一。

int searchRange(vector<int>& nums, int target) {
        int l=0,r=nums.size()-1;
        while(l<r){
            int mid=l+r>>1;
            if(check(mid))r=mid;
            else l=mid+1;
        }
    return l;
}

模板2

我們將區間[l,r]划分成[l,mid-1]和[mid,r]時,更新操作是r=mid-1或者l=mid;這時為了防止死循環,計算mid時需要+1。因為普通的整型計算是向下取整的+1,相當於四舍五入。

int searchRange(vector<int>& nums, int target) {
        int l=0,r=nums.size()-1;
        while(l<r){
            int mid=l+r+1>>1;
            if(check(mid))l=mid;
            else r=mid-1;
        }
    return l;
}

這兩個模板都可以找到想要我們找到的target。舉個例子如下圖我們想要找到9

 

 首先使用模板一

int searchRange(vector<int>& nums, int target) {
        int l=0,r=nums.size()-1;
        while(l<r){
            int mid=l+r>>1;
            if(nums[mid]>=target)r=mid;
            else l=mid+1;
        }
    return l;
}

這樣我們可以看到,模板一找到的最左邊的等於target的數。

因為我們總是完全拋棄左邊,右邊拋棄除nums[mid]的數所以我們選擇check函數為nums[mid]>=target。當數組中有相同的元素的時候,如圖所示,當數組中沒有相同的元素的時候,當nums[r]==target時,nums[mid]<target,l會一步步向右縮直到l=r。

然后我們使用模板二

int searchRange(vector<int>& nums, int target) {
        int l=0,r=nums.size()-1;
        while(l<r){
            int mid=l+r+1>>1;
            if(nums[mid]<=target)l=mid;
            else r=mid-1;
        }
    return l;
}

這樣我們可以看到,模板一找到的最右邊的等於target的數。

因為我們總是完全拋棄右邊,左邊拋棄除nums[mid]的數所以我們選擇check函數為nums[mid]>=target。當數組中有相同的元素的時候,如圖所示,當數組中沒有相同的元素的時候,當nums[l]==target時,nums[mid]>target,r會一步步向右縮直到l=r。

所以對於沒有相同元素的時候,使用兩種模板都可以找到target。對於存在相同元素的時候,按照題意,進行判斷是要找第一個為target還是最后一個為target的使用兩種不同的模板。

這里有一道例題來幫助大家消化。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM