二分查詢的左閉右開和左閉右閉寫法

DawnTraveler發表於2024-04-29

0.參考

參考連結:二分查詢的左閉右開和左閉右閉寫法

1.思路

0. 序言

lower_bound查詢的是升序序列中的第一個出現target的pos,區間應從右向左收縮。
upper_bound查詢的是升序序列中的最後一個出現target的pos,區間應從左向右收縮。
主迴圈判斷本質目的是為了確保整個區間能夠被檢索到。

1.左閉右開

  • 每次迴圈的區間都是[left,right),在二分的時候,搜尋區間去掉mid使得原始區間分為兩塊[left,mid),[mid+1,right),這樣才能保證整個區間都被檢索。
    所以left = mid + 1right = 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 來正確返回下標

相關文章