借用着道题来复习一下 二分查找
说起二分查找 有几个点是要重视的
1.最简单的二分查找
2.上下界二分查找的实现
3.c++ STL 二分查找三兄弟的使用
最简单的二分查找
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 const int maxlen=1e6 + 10; 7 int ar[maxlen]; 8 int BinarySearch(int left,int right,int value); 9 10 int main(){ 11 int n,t,x,i,j; 12 while(~scanf("%d",&n)){ 13 for(i=1;i<=n;i++) 14 scanf("%d",&ar[i]); 15 scanf("%d",&t); 16 while(t--){ 17 scanf("%d",&x); 18 printf("%d ",BinarySearch(1,n,x)); 19 } 20 printf("\n"); 21 } 22 23 return 0; 24 } 25 int BinarySearch(int left,int right,int value){ 26 int middle=(left + right)/2; 27 while(left <= right){ 28 middle=(left+right)/2; 29 if(ar[middle] == value) 30 return middle; 31 else if(ar[middle] < value) 32 left=middle+1; 33 else right=middle-1; 34 } 35 return -1; 36 }
上下界二分查找:其实自己手写上下界二分查找其实也不难。上下界其实就是当你找到一个值无法直接确定这个值是否就是最小或者最大的值,这个时候我们最好的办法就是先记录好这个值,当之后如果有更适合的值就覆盖,没有就统一在最后面返回值。上下界二分查找是一定可以返回值。
下面贴一个自己手写过的下界二分查找代码,其核心算法是无论是上界还是下界二分查找,都会出现多个符合值的情况,那我们每次遇到符合条件的值的时候,我们可以想办法去缩小范围更新,如果更新失败,那么最后直接返回即可。
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxlen=250000 + 10; int ar[maxlen]; int BinarySearch(int left,int right,int value); int main(){ int n,t,x,i,j,ans; while(~scanf("%d %d",&n,&t)){ for(i=1;i<=n;i++) scanf("%d",&ar[i]); while(t--){ scanf("%d",&x); ans=BinarySearch(1,n,x); if(ans == -1) printf("error\n"); else printf("%d\n",ans); } } return 0; } //下界二分查找 //lowbound int BinarySearch(int left,int right,int value){ int middle=(left + right)/2; int pos=-1; while(left <= right){ middle=(left+right)/2; if(ar[middle]>value) right=middle-1; else if(ar[middle] == value){ pos=middle; right=middle-1; } else left=middle+1; } return pos; }
其实在c++ STL的库函数里有三个函数来帮助我们实现二分相关的查找。
这三个函数的头文件是<algorithm>
binary_search 查找某个元素是否出现
函数模板:binary_search(arr[],arr[]+size , indx)
lower_bound:查找第一个大于或等于某个元素的位置
upper_bound:查找第一个大于某个元素的位置
其实这三个函数默认要求给定的数组arr是非递减的,当然如果OJ测试是给定的非递增的,那我们可以在读入的时候做点手脚。
在比较特殊的情况下,例如如果数组中所有的数都小于index那么这两个函数的返回值均是last(数组索引已经越界)
下面给定用STL二分过题的例子:
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxlen=250000 + 10; int ar[maxlen]; int main(){ int n,t,x,i,j,ans,flag; while(~scanf("%d %d",&n,&t)){ for(i=0;i<n;i++) scanf("%d",&ar[i]); while(t--){ scanf("%d",&x); if(binary_search(ar,ar+n,x) == false) printf("error\n"); else printf("%ld\n",lower_bound(ar,ar+n,x) - ar + 1); } } return 0; }
值的关注是这三个STL函数的返回值
binary_search()的返回值是bool类型的 即false or true
lower_bound() 和upper_bound()的返回值是指针类型的,所以如果要求解下标,需要与数组的首地址进行运算。