【算法每日一练]-二分题型 篇1 模板篇

本篇是模板篇

目录

二分查找:

最左模板:

最右模板:

二分精确:

lower_bound和upper_bound

进阶用法lower_bound


     

     

二分查找:

        

我做过的所以二分查找题型基本可以分为两种:最左模型和最右模型

最左模板:

有重复数时候返回最左边的重复数,找不到时候返回第一个大于此数的下标。

(别看写了这么多,其实模板代码就是哪个while循环)

        

#include <bits/stdc++.h>                  //二分查找(必须有序)
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<<l;    //r那里有=,返回左边界l(最左模型)
	return 0;
}

 解释一下我自己探索时候发现的2,3定理:这种二分最终状态要么是处理2个数要么就是3个数(mid加减1)

         

最右模板:

有重复数时候返回最右边的重复数,找不到时候返回最后一个小于此数的下标。

(别看写了这么多,其实模板代码就是哪个while循环)

       


#include <bits/stdc++.h>                  //二分查找(必须有序)
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<<r;   //l那里有=,返回右边界(最右模型)
	return 0;
}

     

二分精确:

这个最好记了,不用管返回l还是r

        

#include <bits/stdc++.h>                 
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<<mid;              //只要精度够,mid,l,r都行
}

       

lower_bound和upper_bound

这两个函数都是针对数字的,字符可以使用find方法

如果恰存在该值,lower_bound返回第一个下标的地址(最左下标),upper_bound返回最后一个的下标 +1的地址(最右下标)

如果不存在该值,都返回第一个大于此数的下标 的地址 (找不到就返回最后的下标+1 也就是end减begin的值)

剩下的不解释了,看注释吧,我全都标记了!!!

        

#include <bits/stdc++.h>
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;//4  表示有4个<5的数
	int pos2=upper_bound(a,a+10,5)-a;//6  表示有6个<=5的数
	
	int pos3=lower_bound(a,a+10,11)-a;
	int pos4=upper_bound(a,a+10,11)-a;//10   表示有10个数
	cout<<pos1<<' '<<pos2<<' '<<pos3<<' '<<pos4;
}

        

进阶用法lower_bound

(struct自定义比较,此时lower_bound已经只是一个名字了,功能已经被你修改了)

        

#include <bits/stdc++.h>
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<b.y;
		return a.x<b.x;	
	}
};
int main(){
	no[0]={1,2};no[1]={2,3};no[2]={3,4};no[3]={3,4};no[4]={4,5};
	node a={2,3};
	int pos =lower_bound(no,no+5,a,cmp())-no;//类名加运算符
	cout<<pos<<' '<<no[pos].x<<' '<<no[pos].y;
}

今天讲了很多干货,好好体会一下啊

  • 28
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值