示例
在生活中,如果需要打电话给 j 某人,如果从电话簿的开始进行查找,那样将耗费大量的时间,所以,一般情况是直接翻页到中间部分进行查找。
又例如玩一个游戏,朋友想一个数字,你进行猜测,朋友告诉你这个数字大于小于或是等于你猜的数字,如果你从1开始猜,那么最后猜对往往可能需要耗费比较多的次数。但如果从中间开始猜,例如50,得出相应的比较关系后,又以此类推,猜25或是75,最后就会以一个比较高的效率猜中这一个数字。
相应的,如果从头开始查找,或者是从尾部开始查找,最坏的结果是需要查找n次(刚好需要查找的是第n个)。而如果使用二分法,需要的次数是log2n。
(对数运算是幂运算的逆运算:例如log10 100 = 2)
例如有一个128个元素的有序列表,最多需要7次遍历就可以获取答案,如果是256个,就最多需要8次遍历。
(简单说一下大O表达式)
例如
O(1)
O(n) 线性时间 例如简单查找
O(logn) 对数时间 例如二分查找
O(nlogn) 例如快速排序
O(n!) 著名的旅行商问题 (一个旅行商要去n个城市,求出最近的路线)
O(n2) 例如冒泡排序
算法运行时间是从其增速的角度度量的,并不以时间为单位,根据具体的需求选择合适的算法。
前提
使用二分查找必须针对一个有序的元素列表,查找到其位置就返回对应下标,否则就返回null。
代码
public static void main(String[] args) {
//给定一个有序的元素列表
int [] arr = new int[]{1,4,5,6,7,9,11,14,16,20};
//目标值
int target = 9;
System.out.println(getTargetByDichotomy(arr, target));
}
/*
二分法
*/
private static int getTargetByDichotomy(int[] arr,int target){
//最小下标
int low = 0;
//最大下标
int high = arr.length;
//只要范围中还有元素就要进行判断
while (low <= high){
//中间下标 每次 low 和 high 变化都要重新计算
int mid = (low+high)/2;
//如果刚好猜对了就返回
if (arr[mid]==target){
return mid;
}
//如果大了就说明在小的那一部分 就修改high
if (arr[mid]>target){
//因为mid 对应不是目标值,所以往下取一个
high = mid - 1;
}else {
//如果小了就说明在大的那一部分,就修改low
low = mid + 1;
}
}
//如果遍历完了都还没有,就返回 -1 或者换成包装类型返回Null
return -1;
}