總綱
思路很簡單,細節是魔鬼。分爲三個常用場景:尋找一個數,尋找左側邊界,尋找右側邊界。最後給出力扣上的題目例子。
還可以在GitHub上觀看哦。AlgorithmNotes
基礎框架
int binarySearch(int[] nums, int target) {
int left = 0, right = ...;
while(...) {
int mid = (right + left) / 2;
if (nums[mid] == target) {
...
} else if (nums[mid] < target) {
left = ...
} else if (nums[mid] > target) {
right = ...
}
}
return ...;
}
- 把所有情況都寫清楚,展示所有細節。
- mid = left + (right - left) / 2,防止溢出。
- 三個框架可以合成一個,但適用面很小,不如單獨的左區間或右區間使用廣。
尋找一個數
int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid - 1;
}
return -1;
}
最基礎的二分查找,每次查找都是左閉右閉區間。
- 循環條件是 <=;
- 更新是 left=mid+1,right=mid-1。
必要條件是數組內無重複整數。
尋找左側邊界
int left_bound(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0;
int right = nums.length;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
right = mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid;
}
}
return left;//此處返回left,right都可,因爲相等
}
每次查找都是左閉右開區間。
- 循環條件是 left < right;
- 更新是 left = mid + 1, right = mid,可以理解爲下一次搜索區間是 [left,mid), [mid+1,right)
- 每次找到target時,因爲存在重複數字且要找的是左邊界,所以不斷向左收縮, right = mid。
尋找右側邊界
int right_bound(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0, right = nums.length;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
left = mid + 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid;
}
}
return left - 1;
}
- 循環條件是 left < right;
- 更新是 left = mid + 1, right = mid,可以理解爲下一次搜索區間是 [left,mid), [mid+1,right);
- 每次找到target時,因爲存在重複數字且要找的是右邊界,所以不斷向右收縮, left = mid + 1;
- 返回 left - 1,因爲更新時 left = mid + 1,所以循環結束時 nums[left-1] 纔是target。
題目
題號 | 題目 | 鏈接 |
---|---|---|
704 | 二分查找(打板題) | 105265723 |
33 | 搜索旋轉排序數組 | 105265887 |
35 | 搜索插入位置(打板題) | 105265922 |
153 | 尋找旋轉排序數組中的最小值 | 105265935 |
154 | 尋找旋轉排序數組中的最小值II | 105265998 |
162 | 尋找峯值 | 105266055 |
275 | H指數II | 105266073 |