0.參考
參考連結:二分查詢的左閉右開和左閉右閉寫法
1.思路
0. 序言
lower_bound查詢的是升序序列中的第一個出現target的pos,區間應從右向左收縮。
upper_bound查詢的是升序序列中的最後一個出現target的pos,區間應從左向右收縮。
主迴圈判斷本質目的是為了確保整個區間能夠被檢索到。
1.左閉右開
-
每次迴圈的區間都是[left,right),在二分的時候,搜尋區間去掉mid使得原始區間分為兩塊[left,mid),[mid+1,right),這樣才能保證整個區間都被檢索。
所以left = mid + 1
和right = mid
-
主迴圈判斷條件:left< right,這和我們在其他迴圈中是一樣的。
比如for (int i= 0; i< nums.size(); ++i)
左閉右開的寫法更常見,c++中迭代器返回的end就是右開的。
在主迴圈跳出的時候,其實是[left,left),這個搜尋空間為空,主迴圈確保了整個區間的檢索。
1.1 lower_bound
實現lower_bound關鍵是target == nums[mid]的時候,我們仍然讓right = mid,實現從右向左收縮.
int lower_bound(vector<int>& nums, int target){
int left = 0, right = nums.size(), mid;
while (left < right){
mid = left + (right - left)/2;
if (nums[mid] == target){
right = mid;
}else if (nums[mid] < target){
left = mid + 1;
}else if (nums[mid] > target){
right = mid;
}
}
// 邊界
if (left >= nums.size() || nums[left] != target) return -1;
return left;
}
upper_bound
- 實現 upper_bound關鍵是target = nums[mid]的時候,left = mid + 1 實現從左向右搜尋。
- 最終推出迴圈返回的left是最後出現target的下一位,需要 left - 1 來正確返回下標