一、二分法思想
二分法查找针对的是一个有序的数据集合,每次通过与区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0.
故时间复杂度就是O(logn)
二分查找的递归与非递归实现
1、二分查找非递归实现
int binarySearchFirstOne(vector<int> &a, int value) {
int n = a.size();
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] >= value)
high = mid - 1;
else
low = mid + 1;
}
if (low < n && a[low] == value) {
return low;
}
else {
return -1;
}
}
二分查找易错的地方
循环退出的条件
注意是low <= high,而不是low<high.
mid的取值
如果写成 mid (low+high)/2是有问题,如果low和high比较大,两者的和可能会溢出改进的方案low+(high-low)/2,但是计算机位运算比除法快,故可改成low+((high-low)>>1)
二分法的递归实现
int bsearchInternally(vector<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);
}
}
int bsearch(vector<int>& a, int n, int val) {
int res= bsearchInternally(a, 0, n - 1, val);
return res;
}
三、二分法查找应用场景
二分查找依赖顺序表结构
二分查找不能依赖如链表的的其他结构,主要原因是二分查找算法需要按照下标随机访问元素,链表随机访问的时间复杂度是O(n),使用链表存储,二分查找的时间复杂度就会变得很高
二分查找针对的有序数组
二分查找对数据要求必须是有序的,如果数据没有序,则需要先排序
数据量太小或数据量太大也不适合二分查找
参考: