二分查詢筆記
阿新 • • 發佈:2021-01-31
技術標籤:Leetcode
參考文章
詳解二分查詢演算法
ps. 這篇文章細節解釋得非常好。
相關習題
尋找一個數:https://leetcode-cn.com/problems/binary-search/
尋找左右邊界:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/
核心思想
- 查詢的區間為[left,right] 或者 [left,right) 。兩種方式皆可,但注意程式碼前後的統一性。本篇筆記只使用[left,right]的區間表示方式。
- 迴圈的停止條件為搜尋區間為空。
while(left<=right){...}
,迴圈結束時left == right+1
(2) 當查詢區間為[left,right)時,迴圈為while(left<right){...}
,迴圈結束時有left == right。 - 使用mid切分陣列。
(1) 使用[left,right]時,分割後的陣列為[left,mid-1] 和 [mid+1,right],所以更新時left=mid+1,right=mid-1
。
(2) 使用[left,right)時,分割後的陣列為[left,mid) 和 [mid+1,right),所以更新時left=mid+1,right=mid
- 注意事項:使用
int mid=left+(right-left)/2;
防止溢位(養成習慣!)
尋找一個數
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0, right=nums.size()-1;//區間為[left,right]
while(left<=right){ //迴圈前提條件:保證搜尋區間不為空,==時仍有元素
int mid=left+(right-left)/2;//防止溢位
if (nums[mid]==target)
return mid;
else if(nums[mid]<target)
left=mid+1;//[mid+1,right]
else
right=mid-1;//[left,mid-1]
}
return -1;
}
};
尋找左邊界
迴圈結束時,left表示陣列中第一個nums[i]>=target
的索引,其中0<=left<=nums.size()。
因此,迴圈結束後需要
- 判斷
left==nums.size()
- 根據
nums[left]==target
判斷target是否存在。
class Solution {
public:
int searchRange(vector<int>& nums, int target) {
int n=nums.size();
//尋找左邊界
int left=0, right=n-1;//[left,right]
while(left<=right){ //迴圈條件:搜尋的區間不為空
int mid=(right-left)/2+left;//將陣列拆分成[left,mid-1]和[mid+1,right]
if(nums[mid]>=target)
right=mid-1;
else
left=mid+1;
}
//迴圈結束時left==right+1。其中left為第一個滿足nums[i]>=target的索引,0<=left<=n,需要判斷nums[left]是否為所求
if(left==n || nums[left]!=target)
return -1;
return left;
}
};
尋找右邊界
迴圈結束時,left表示陣列中第一個nums[i]>target
的索引,其中0<=left<=nums.size(),需要判斷left-1是否為要尋找的target。
因此,迴圈結束後需要
- 判斷
left==0
- 根據
nums[left-1]==target
判斷target是否存在。
class Solution {
public:
int searchRange(vector<int>& nums, int target) {
int n=nums.size();
//尋找右邊界
int left=0, right=n-1;//[left,right]
while(left<=right){
int mid=(right-left)/2+left;//迴圈條件:搜尋的區間不為空
if(nums[mid]<=target)
left=mid+1;
else
right=mid-1;
}
//迴圈結束時left==right+1。其中left為第一個滿足nums[i]>target的索引,0<=left<=n,需要判斷nums[left-1]是否為所求
if(left==0 || nums[left-1]!=target)
return -1;
return left-1;
}
};