无处不在的二分思想
- 生活中猜数
- 适用场景:有序数组查找
-
时间复杂度 O(logn)
- 有时甚至会比O(1)时间复杂度还高效
- 2的32次方(42亿)也只需要比较32次
二分的递归与非递归实现
-
基础版的二分查找
- 有序数组
- 不存在重复元素
-
需要注意的点
-
循环退出条件:low<=high
-
mid取值:mid=(low+high)/2 可能造成溢出
-
low+(high-low)/2\
-
用移位代替除法 low+((high-low)>>1)
-
-
low和high更新
- low=mid 或者 high=mid可能导致死循环\
-
| ``` //顺序查找
public int bsearch(int[] a, int n, int value) { int low = 0; int high = n - 1; while (low <= high) { int mid = (low + high) / 2; if (a[mid] == value) { return mid; } else if (a[mid] < value) { low = mid + 1; } else { high = mid - 1; } } return -1; }
//递归查找
// 二分查找的递归实现 public int bsearch(int[] a, int n, int val) { return bsearchInternally(a, 0, n - 1, val); } private int bsearchInternally(int[] a, int low, int high, int value) { if (low > high) return -1; int mid = low + ((high - low) >> 1); if (a[mid] == value) { return mid; } else if (a[mid] < value) { return bsearchInternally(a, mid+1, high, value); } else { return bsearchInternally(a, low, mid-1, value); } }
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
# 二分应用场景的局限性
- 基于数据,可以顺序查找
- 链表不可以
- 针对有序数据
- 先排序再二分
- 数据量太小或太大不需要二分查找
- 数据量小 遍历即可
- 数据量大 内存吃不消
# 总结
- 二分查找时间复杂度O(logn)
- 条件苛刻
- 数组
- 有序
- 数据规模适中