在這里我們一共有兩個模板
模板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的使用兩種不同的模板。
這里有一道例題來幫助大家消化。