二分查找(模板)
转载自:https://www.jianshu.com/p/0f823fbd4d20
二分查找很好写,却很难写对,出错原因主要集中在判定条件和边界值的选择上,很容易就会导致越界或者死循环的情况。
下面对二分查找及其变形进行总结:
首先,二分查找的序列必须是有序的、有序的、有序的
如果环境允许,可以用库函数直接使用
二分查找的函数有 3 个: 参考:https://www.cnblogs.com/Tang-tangt/p/9291018.html
头文件是#include<algorithm>
lower_bound(起始地址,结束地址,要查找的数值) - 起始地址
upper_bound(起始地址,结束地址,要查找的数值) - 起始地址
binary_search(起始地址,结束地址,要查找的数值)
说明:lower_bound()和upper_bound()返回的地址,都是从位置1开始算起的,[ first, last ),即first最小是从1开始的
1 函数lower_bound()
功能:函数lower_bound()在[ first,last )区间进行二分查找,返回大于或等于val的第一个元素位置。
注意:如果val不存在,则返回last+1的位置,位置last+1是越界的!!
2 函数upper_bound()
功能:函数upper_bound()在[ first,last )区间进行二分查找,返回大于val的第一个元素位置
注意:如果val刚好在上边界last的位置上,upper_bound()返回0;如果val不存在,则返回last+1的位置,而位置last+1是越界的!!
3 函数binary_search()
功能:判断查找的数是否存在,返回的是一个bool值。
#include<iostream> #include<algorithm> using namespace std; int a[1005]; int main() { int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n); int x,y; cout<<binary_search(a,a+n,5)<<endl; x=upper_bound(a,a+n,5)-a; y=lower_bound(a,a+n,5)-a; cout<<a[x]<<endl; cout<<a[y]<<endl; return 0; }
1. 最基本的二分查找
int a[100005]; int find1(int target, int l,int r)//l,r是查找的左右区间 { int left = l, right = r, mid; while (left <= right) { mid = left + (right - left) / 2; if (a[mid] == target) return mid; else if (a[mid] > target) right = mid - 1; else left = mid + 1; } return -1; }
其中,有几个要注意的点:
- 循环的判定条件是:
low <= high
- 为了防止数值溢出,
mid = low + (high - low)/2
- 当
A[mid]
不等于target
时,high = mid - 1
或low = mid + 1
2. 当目标值有多个的时候,返回从左往右的第一个目标值。(目标值区域的左边界/查找与目标值相等的第一个位置/查找第一个不小于目标值数的位置)
eg:
A = [1,3,3,5, 7 ,7,7,7,8,14,14]
target = 7
return 4
int a[100005]; int find2(int target,int l,int r) { int left = l, right = r, mid; while (left <= right) { mid = left + (right - left) / 2; if (target <= a[mid]) right = mid - 1; else left = mid + 1; } if (left <= r && a[left] == target) return left; else return -1; }
3. 当目标值有多个的时候,返回从左往右的最后一个目标值。(查找目标值区域的右边界/查找与目标值相等的最后一个位置/查找最后一个不大于目标值数的位置)
eg:
A = [1,3,3,5,7,7,7, 7 ,8,14,14]
target = 7
return 7
int a[100005]; int find3(int target, int l,int r) { int left = l, right = r, mid; while (left <= right) { mid = left + (right - left) / 2; if (target >= a[mid]) left = mid + 1; else right = mid - 1; } if (right >= 0 && a[right] == target) return right; else return -1; }