本篇是模板篇
目录
二分查找:
最左模板:
最右模板:
二分精确:
lower_bound和upper_bound
进阶用法lower_bound
我做过的所以二分查找题型基本可以分为两种:最左模型和最右模型
有重复数时候返回最左边的重复数,找不到时候返回第一个大于此数的下标。
(别看写了这么多,其实模板代码就是哪个while循环)
#include //二分查找(必须有序)
using namespace std;
const int INF=1e5;
int main(){
int a[100]={5,5,5,5,7,8,9,9,11,13,14,14,15};
//如果是逆序的,那么在判断时候把a[mid]>=x变成a[mid]<=x即可
for(int i=13;i<100;i++)a[i]=INF;//查找数组时候,千万不要越界查找
int mid=0,l=0,r=100,x;
cin>>x;
while(l<=r){
mid=(l+r)>>1; //最左二分模板。有重复数时,返回第一个(可以用2,3定理证明)
if(a[mid]>=x) r=mid-1; //若找不到,则返回第一个大于此数的下标(故若过大,则返回最后一个元素下标+1)
else l=mid+1;
}
cout<
解释一下我自己探索时候发现的2,3定理:这种二分最终状态要么是处理2个数要么就是3个数(mid加减1)
有重复数时候返回最右边的重复数,找不到时候返回最后一个小于此数的下标。
(别看写了这么多,其实模板代码就是哪个while循环)
#include //二分查找(必须有序)
using namespace std;
const int INF=1e5;
int main(){
int a[100]={5,5,5,5,7,8,9,9,11,13,14,14,15};
//如果是逆序的,那么在判断时候把a[mid]>=x变成a[mid]<=x即可
for(int i=13;i<100;i++)a[i]=INF;//查找数组时候,千万不要越界查找
int mid=0,l=0,r=100,x;
cin>>x;
while(l<=r){
mid=(l+r)>>1; //最右二分模板:若有重复数时,返回最后一个
if(a[mid]<=x) l=mid+1; //若找不到,则返回最后一个小于此数的下标(故若过大,则返回最后一个元素下标)
else r=mid-1;
}
cout<
这个最好记了,不用管返回l还是r
#include
using namespace std;
int main(){ //二分精确
double l=0,r=10,mid=0,x;
cin>>x;
while(r-l>0.001){ //这里控制精度
mid=(l+r)/2;
if(mid>=x) r=mid; //等号不影响
else l=mid;
}
cout<
这两个函数都是针对数字的,字符可以使用find方法
如果恰存在该值,lower_bound返回第一个下标的地址(最左下标),upper_bound返回最后一个的下标 +1的地址(最右下标)
如果不存在该值,都返回第一个大于此数的下标 的地址 (找不到就返回最后的下标+1 也就是end减begin的值)
剩下的不解释了,看注释吧,我全都标记了!!!
#include
using namespace std;
int main(){
int a[10]={1,2,3,4,5,5,7,8,9,10};
//如果恰存在该值,lower_bound返回第一个下标(最左下标),upper_bound返回最后一个的下标 +1(最右下标)
int pos1=lower_bound(a,a+10,5)-a;//第一个大于或等于的下标 5的下标为4
int pos2=upper_bound(a,a+10,5)-a;//第一个大于的下标 7的下标为6
//如果不存在该值,都返回第一个大于此数的下标 (找不到就返回最后的下标+1 也就是end减begin的值)
int pos3=lower_bound(a,a+10,11)-a;
int pos4=upper_bound(a,a+10,11)-a;
cout<
(struct自定义比较,此时lower_bound已经只是一个名字了,功能已经被你修改了)
#include
using namespace std;
struct node{
int x;int y;
}no[10];
struct cmp{ //在结构体cmp中重载()运算符,后面有3个const
bool operator() (const node a,const node b)const{
if(a.x==b.x)return a.y
今天讲了很多干货,好好体会一下啊