mid 最好写成 mid = left + ( right - left ) / 2 以防止溢出
左侧边界
#include<bits/stdc++.h>using namespace std;int main(){int n,a[100005],q;scanf("%d",&n); //输入数组元素个数for(int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("%d",&q); //输入询问次数while(q--){ //循环q次int t,l=1,r=n;scanf("%d",&t);//核心while(l<=r){int mid=l+(r-l)/2;if(a[mid]>=t) r=mid-1;else l=mid+1;}if(a[l]!=t) l=-1; //若查找的数不存在,输出-1printf("%d ",l);}return 0;}
lower_bound()
lower_bound ( first , last , val ) 用来查找 [ first , last ) 范围内第一个大于或等于val的元素的位置。如果是数组,返回该位置的指针;如果是容器,返回该位置的迭代器。若查找失败,返回 last 。
#include<bits/stdc++.h>using namespace std;int main(){int n,a[100005],q;scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("%d",&q);while(q--){int t;scanf("%d",&t);int* i=lower_bound(a+1,a+n+1,t);if(*i!=t) i=a-1;printf("%d ",i-a);}return 0;}
右侧边界
#include<bits/stdc++.h>using namespace std;int main(){int n,a[100005],q;scanf("%d",&n); //输入数组元素个数for(int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("%d",&q); //输入询问次数while(q--){ //循环q次int t,l=1,r=n;scanf("%d",&t);//核心while(l<=r){int mid=l+(r-l)/2;if(a[mid]<=t) l=mid+1;else r=mid-1;}if(a[r]!=t) r=-1; //若查找的数不存在,输出-1printf("%d ",r);}return 0;}
upper_bound()
upper_bound ( first , last , val ) 用来查找 [ first , last ) 范围内第一个大于val的元素的位置。如果是数组,返回该位置的指针;如果是容器,返回该位置的迭代器。若查找失败,返回 last 。
#include<bits/stdc++.h>using namespace std;int main(){int n,a[100005],q;scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("%d",&q);while(q--){int t;scanf("%d",&t);int* i=upper_bound(a+1,a+n+1,t);i--;if(*i!=t) i=a-1;printf("%d ",i-a);}return 0;}
二分答案
可以用于解决求最大值最小或最小值最大的问题
应用:防御迷阵、跳石头等
自己总结的一种用法:如果mid可能在查找范围内,可以先让左指针移到mid+1的位置,最后返回 L-1
