二分查找学了很长时间了,但是其复杂的边界情况和取整方式和区间开闭方式并不清楚,现在就来总结和归纳一些细节
先贴一下二分查找的基本步骤:
逐步缩小范围法是一种常见的思维方法。二分查找便是基于这种思路,它遵循分治三步法:
1. 把原序列划分成元素个数尽量接近的两个子序列,然后递归查找。
2. 二分查找只适用于有序序列。有一组数已经按从小到大(或从大到小)排序
3. 时间复杂度为O(logn)。
目标:输入一个数x,在这组数查找是否有x
1. 确定三个关键下标的初值:bott=0, top=8, mid=(bott+top)/2;
2. 判断要找的数x是否等于a[mid]
① x==a[mid] 找到,结束
x<a[mid] 在a[bott]—a[mid-1]之间继续查找x
top=mid-1; mid=(bott+top)/2;
③ x>a[mid] 在a[mid+1]—a[top]之间继续查找x
bott=mid+1; mid=(bott+top)/2;
二分搜索实例:
设在数组a中顺序放了以下9个元素:
检索x=9, 9==a[4], 一次比较就成功, 最好情况
检索x=-15, -15<a[4], -15<a[1], -15==a[0], 3次比较, 成功
检索x=101, 101>a[4], 101>a[6], 101>a[7], 101==a[8],
4次比较, 成功
检索x=8, 8<a[4], 8>a[1], 8>a[2], 8>a[3], 4次比较, 不成功
尽管可以递归实现,但一般把二分查找写成非递归的;
二分搜索迭代实现
伪码
binarySearch(A,key)
bote = 0;
top = n;
while bott < top
mid = (bott +top) / 2
if A[mid] == key
return mid
else if key <A[mid]
top = mid
else
bott = mid+1
return no foud
二分搜索递归实现
分析:若使用递归算法,需要获得递归的终止条件和递推关系
递归函数的终止条件:
1. 搜索成功,即x == a[mid],返回mid
2. 搜索不成功,即 bott > top,返回-1
递归函数的递推关系:
1. 如果x>a[mid],返回find(a,x,mid+1,top)
2. 如果x<a[mid],返回find(a,x,bott,mid-1)
二分查找的边界情况&取整方式和区间开闭方式
中位数有两个:
1.下中位数:mid = (length - 2) / 2
2.上中位数:mid = lengh / 2
常用下中位数,int自动向下取整
mid = (length-1) / 2;
取闭区间不容易错[l , r];
mid = l + (r - l) / 2;
*会溢出的写法
mid = (l + r) / 2;
*不要以了== r为终结条件,正确的终结条件是l>h,就是搜索空间为空。
对其进行分类:
取整方式:向下取整 向上取整 (共2种)
m = l + ((r + 1 - l) >> 1);//向上取整
if (a[m] <= key) l = m;
else r = m - 1;
向上取整l = m;最后返回l;
m = l + ((r - l) >> 1);//向下取整
if (a[m] <= key) l = m + 1;
else r = m;
向下取整r = m;最后返回r;
区间开闭:闭区间 左闭右开区间 左开右闭区间 开区间 (共4种)
问题类型:
对于不下降序列a,求最小的i,使得a[i] = key
对于不下降序列a,求最大的i,使得a[i] = key
对于不下降序列a,求最小的i,使得a[i] > key
对于不下降序列a,求最大的i,使得a[i] < key
对于不上升序列a,求最小的i,使得a[i] = key
对于不上升序列a,求最大的i,使得a[i] = key
对于不上升序列a,求最小的i,使得a[i] < key
对于不上升序列a,求最大的i,使得a[i] > key
(共8种)
综上所述,二分查找共有 种写法。
关于STL中的二分查找:https://blog.csdn.net/u010700335/article/details/41323427
感谢大佬:
二分查找有几种写法?它们的区别是什么?
LightGHLi的回答 - 知乎https://www.zhihu.com/question/36132386/answer/105595067
点击打开链接