第1章:二分查找
1 代码实现
public boolen binSearch(int[] numbers, int target){
//判断数组是否为空
if(numbers == null) return false;
//定义初始最小、最大索引
int low = 0;
int high = numbers.length - 1;
//确保不会出现重复查找,越界
while(low <= high){
//计算出中间索引值
//int mid = (end + start)>>>1 ;//防止溢出
int mid = (high - low)/2 + low;//防止溢出
if(numbers[mid] == target){
//查找成功返回
return true;
}
else(numbers[mid] > target){
//继续在R[low..mid-1]中查找
high = mid - 1;
}
else{
//继续在R[mid+1..high]中查找
low = mid + 1;
}
}
return false;
}
2.注意细节
(1) 使用(low+high)/2会有整数溢出的问题
(问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题
(2) int middle = start + (end - start) >> 1;
-
此处的右移可以替换成除2的方式,因为不会有溢出的问题。但右移的效率更高
-
这种计算方法其实是在直观思维的基础之上做了转换
-
直观思维是相加除2直接求中间值,
-
这种计算方式等于是根据起始值或结束值如何得到中间值
-
这样描述似乎很乱,举个栗子就是假设起始值是2,结束值是6,我们可以很容易的求出中间值为4。但其实这个
-
是指针对起点0来说。对于起始值呢,这个4就是起始值加2得到的。这个加的2是通过结束值-起始值,然后除2得到的。
-
根据java向下取整的计算方式,我们不能用结束值减去差值的方式得到中间值
(3) int middle = (end + start) >>> 1;
-
这种计算方式加法会溢出,但无符号右移保证了计算的正确性
-
无符号右移后高位补0,不会得到负数
3 其他
public static void main(String[] args) {
int low = Integer.MAX_VALUE;
int high = Integer.MAX_VALUE;
System.out.println(low);//2147483647
System.out.println(high);//2147483647
System.out.println(low + high);//-2
System.out.println("---------");
System.out.println((low + high)/2);//-1
System.out.println((low + high)>>2);//-1
System.out.println((low + high)>>>2);//2147483647
System.out.println((high - low)/2 + low);//2147483647
}
// 但没有<<<