如下兩種實現方式,right 邊界的取值,直接影響著演算法的實現細節,這些細節稍不小心就會犯錯。二分查詢看似簡單,實則不然,真正能考慮到所有細節,把**寫準確是很不容易的。
int binarysearch(int nums, int target)
return -1;
}
int binarysearch(int nums, int target)
return -1;
}
1. while 迴圈的條件中 <=,< 有什麼區別?
答:如果初始化 right 的賦值是 nums.length-1,即最後乙個元素的索引,相當於兩端都閉區間 [left, right],則while 迴圈的條件中 用<=。如果初始化 right 是 nums.length,相當於左閉右開區間 [left, right),則 while 迴圈的條件中 <,因為索引大小nums.length 是越界的。
2. 為什麼第一種演算法是 left = mid + 1,right = mid - 1,第二種演算法是 left = mid + 1,right = mid ,如何判斷?
答:這也是二分查詢的乙個難點,不過只要你能理解前面的內容,就能夠很容易判斷。剛才明確了「搜尋區間」這個概念,如果演算法的搜尋區間是兩端都閉的,即 [left, right]。那麼當我們發現索引 mid 不是要找的 target 時,如何確定下一步的搜尋區間呢?
當然是 [left, mid - 1] 或者 [mid + 1, right] ,因為 mid 已經搜尋過,應該從搜尋區間中去除。相應的,如果演算法的搜尋區間是左閉右開的,即 [left, right),則當mid 不是要找的 target 時,下一步的搜尋區間是 [left, mid) 或者 [mid + 1, right)。
int left_bound(int nums, int target) else if (nums[mid] < target) else if (nums[mid] > target)
}// target 比所有數都大
if (right == nums.length) return -1;
// 類似之前演算法的處理方式
return nums[right] == target ? right : -1;
}
1. 為什麼該演算法能夠搜尋左側邊界?
答:關鍵在於對於 nums[mid] == target 這種情況的處理:
if (nums[mid] == target) else if (nums[mid] < target) else if (nums[mid] > target)
}if (left == 0) return -1;
return nums[left-1] == target ? (left-1) : -1;
}1. 為什麼這個演算法能夠找到右側邊界?
答:類似地,關鍵點還是這裡:
if (nums[mid] == target) {
left = mid + 1;
當 nums[mid] == target 時,不要立即返回,而是增大「搜尋區間」的下界 left,使得區間不斷向右收縮,達到鎖定右側邊界的目的。另外,為什麼最後返回 left - 1 ?while 迴圈的終止條件是 left == right,所以返回 left -1 或 right - 1是一樣的。由於區間向右收縮的過程中是 left = mid + 1 賦值,所以迴圈終止的時候肯定 nums[left] != target, 而nums[left - 1] 才可能是右側邊界。
二分查詢那些事
二分查詢可以學習如何上下界問題非常有幫助。首先討論統一介面的情況,便於實現其他演算法的版本。這裡使用兩種思路去討論演算法的實現形式,第一種以 減而治之 的策略實現並從查詢行為平衡度等方面對演算法進行改進,第二種直接從通過規則的討論直接討論演算法組成,各層判斷。語義定義 在有序向量的區間 l,h 內查...
二分查詢爬過的坑
二分查詢看似簡單,但是刷多了二分查詢的題,就會遇到很多意向不到的坑,真的是實踐出真知啊,現總結下二分查詢遇到的坑。一 樸素版二分查詢 在有序陣列中查詢關鍵字,找到就返回下標,不管重複不重複。樸素版二分查詢 int bitsearch int a,int n,int k else if a mid k...
二分查詢有個坑
內容會持續更新,有錯誤的地方歡迎指正,謝謝 例題 在序列 22,34,55,77,89,93,99,102,120,140 中,採用二分查詢,分別查詢77,34,99,所需的查詢次數分別為 答案 4,2,4 理由 假設低下標用low表示,高下標用high表示 查詢77 開始low 0,high 9 ...