演算法(第4版) 學習筆記二——二分查詢的普通實現與遞迴實現
阿新 • • 發佈:2019-01-22
以查詢某個特定元素在已排序陣列中的索引為例,且此陣列為從小到大排序。
演算法思路:
1、取第一個索引和最後一個索引代表兩個遊標,一個lo,一個hi
2、取lo和hi的中間值,即為mid,如下圖所示,中間值為4
3、取出中間索引處的值,與輸入值i比較
- 假如比i大,那麼說明我們要的值在上面,把hi值變成剛剛取的中間索引值,即hi=mid-1,lo值保持不變,
- 假如比i小,那麼說明我們要的值在下面,把lo值變成剛剛取得中間索引值,即lo=mid+1,hi值保持不變
- 假如兩個值相等,那麼返回mid
注1:為什麼需要mid減1或加1?
4、重複2~3步,直到lo>hi
注2:為什麼是>而不是>=?
普通實現:
public static int indexOf(int i, int[] a) {
int lo = 0;//定義上索引
int hi = a.length - 1;//定義下索引
while(lo<=hi) {
int mid = (lo + hi) / 2;
if(a[mid]>i) hi = mid - 1;//假如比i大
else if(a[mid]<i) lo = mid + 1;//假如比i小
else return mid;
}
return -1;//沒找到
}
遞迴實現:
public static int indexOf(int i, int[] a) {
indexOf(i, a, 0, a.length-1);
}
public static int indexOf(int i, int[] a, int lo, int hi) {
if(lo>hi) return -1;
int mid = (lo + hi) / 2;
if(a[mid]>i) return indexOf(i, a, lo, mid-1);
else if(a[mid]<i) return indexOf(i, a, mid+1 , hi);
return mid;
}
注1解答:因為mid已經不滿足條件,我們已經不需要它了
注2解答:因為在=出現的時候,mid = lo = hi,而這個mid值是上一步的mid減1或加1得到的,即這兩個mid不可能相等,為了驗證最後的這個mid是不是我們需要的mid,所以還需要這兩個值相等,而下一步要麼是lo = mid + 1 > hi,要麼是hi = mid - 1 < lo,都會不滿足lo<=hi的條件而跳出迴圈