圖解算法與數據結構
1、前言
上次講到的更的二分查找模板在很多地方讓我使用起來不是特別的舒服,感謝B站上的y大佬,讓我找到了一個新的模板!!!
下面一起來看看吧!!!
本次的模板應對重複元素也可以~
2、代碼
模板一:
// C
int lower_bound(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize-1;
while(left < right){ // 搜索區間[first, last)不爲空
// 防溢出
int mid = left + right >> 1;
if(nums[mid] >= target) right = mid;
else left = mid + 1;
}
return left; // right也行,因爲[left, right)爲空的時候它們重合
}
首先一定要明確,數組是升序的!!!
如果中點大於等於 target
,表示目標在左側,數組範圍應該從 [left, right]
變成 [left, mid]
,否則,就從 [left, right]
變成 [mid+1, right]
。
爲什麼 right
不加一?
因爲是大於等於,帶着等於,也就是 mid
有可能是我們的解!!!
模板二:
// C
int lower_bound(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize-1;
while(left < right){ // 搜索區間[first, last)不爲空
// 防溢出
int mid = left + right + 1 >> 1; // 防止死循環,mid加1
if(nums[mid] <= target) left = mid;
else right = mid + 1;
}
return left; // right也行,因爲[left, right)爲空的時候它們重合
}
首先一定要明確,數組是升序的!!!
如果中點小於等於 target
,表示目標在右側,數組範圍應該從 [left, right]
變成 [mid, right]
,否則,就從 [left, right]
變成 [left, mid+1]
。
爲什麼 left
不加一?
因爲是小於等於,帶着等於,也就是 mid
有可能是我們的解!!!
- 模板一:區間
[left, right]
劃分成[left, mid]
和[mid + 1, right]
時,其更新操作是right = mid
或者left = mid + 1;
,計算mid
時不需要加1
。 - 模板二:區間
[left, right]
劃分成[left, mid - 1]
和[mid, right]
時,其更新操作是r = mid - 1
或者l = mid;
,此時爲了防止死循環,計算mid
時需要加1
。
3、實例(LeetCode 704題)
首先看一下題目,
代碼:
int search(int* nums, int numsSize, int target){
int left=0;
int right=numsSize-1;
while(left<right){
int mid=left+right >> 1;
if(nums[mid]>=target){
right=mid;
}
else{
left=mid+1;
}
}
if(nums[left]==target) return left;
return -1;
}
作爲最經典的二分查找題,這個題依舊複合我們的模板,沒錯就是 模板一!!!
唯一不同的是,要注意判斷結果,不能只寫個 left
,因爲是存在 -1
的情況的,加個 if(nums[left]==target) return left;
就好了。
這裏自然又更容易的方法,但是 練習模板,萬法接通,每日一遍,養成習慣!!!
附上最經典的二分查找解法:
// C
int search(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize - 1;
while (left <= right) {
// 最好這麼寫,不然會內存溢出
// 同時還能減少運行時間!!!
int mid = (left + right) >> 1;
// 等於的情況最簡單,首先判斷,沒準一下就中了!
if (nums[mid] == target) {
return mid;
}
else if (nums[mid] < target) {
// 左邊界更新爲 mid + 1
left = mid + 1;
}
else {
// 右邊界更新爲 mid - 1
right = mid - 1;
}
}
return -1;
}
如果有幸幫到你,請幫我點個【贊】,給個【關注】!如果能順帶【評論】給個鼓勵,我將不勝感激。
如果想要更多的資源,歡迎關注 @我是管小亮,文字強迫症MAX~