二分查找中大于小于,甚至判断条件中的 < <= 很容易弄混。下面一起来捋清楚,保证了解原理,不会再错。重点的概念在于选区的区间!
我建议选取的区间为左闭右闭,即[l,r]。当然其他方式也可以,我们不做讲述。
因此需要注意以下三点即可:
1.r = arr.length()-1
而不是length(),这样使得r为末数的下标,有意义。
2. 判断终止条件为l < = r
,因为 l,r 都是寻找目标,当其相等时,代表还有一个待验证目标。
3. 每次缩小范围时,l = mid-1, r = mid + 1
。原因很简单,我们已经判断过mid 并不是我们的target,因此下次判断的区间并不需要包含mid!
package com.mySearch;
public class binSearch {
// 递归方法,被调用方
public static int bsearch(int[] arr, int l, int r, int target) {
if (l <= r) {
int mid = l + (r - l) / 2;
if (arr[mid] == target) {
return mid;
} else if (target < arr[mid] ) {
// 由于区间要的是左闭右闭区间,且arr[mid]不是答案,因此,mid-1
return bsearch(arr, l, mid - 1, target);
} else if (target > arr[mid]) {
// 同上,mid+1
return bsearch(arr, mid + 1, r, target);
} else {
return -1;
}
} else {
return -1;
}
}
// 递归方法入口,调用方
public static int search(int[] arr, int target) {
// 当我们确定 r为len-1时,代表我们整个区间要的是[l,r]
int l = 0, r = arr.length - 1;
return bsearch(arr, l, r, target);
}
// 非递归方法
public static int searchwithwhile(int[] arr, int target) {
// 细节与递归相同
int l = 0, r = arr.length - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (target == arr[mid]) {
return mid;
} else if (target < arr[mid]) {
r = mid - 1;
} else if (target > arr[mid]) {
l = mid + 1;
} else {
return -1;
}
}
return -1;
}
public static void main(String[] args) {
int target = 1;
System.out.println(search(new int[]{1, 2, 3, 5, 6, 7}, target));
System.out.println(searchwithwhile(new int[]{1, 2, 3, 5, 6, 7}, target));
}
}