二分总结。

当在找一个边界的时候,我们要保证这个边界把左右两部分分成两个不同性质的部分,比如如果要在一个数组中查找一个数的话,我们目的是查找这个数,实际上是查找他的边界,所以我们需要先把这个数组排序,排序之后这个数的左边都小于等于他,右边都大于等于他,然后我们就可以利用性质来找边界,先定义左边界l和右边界r,然后while(l<r)的时候找中间值mid=(l+r)/2,然后根据具体实例进行lr边界的变化,核心代码是:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,x;
int a[100005];
for(int i=0;i<n;i++)cin>>a[i];//输入a数组的数
	sort(a,a+n);//千万记得排序
cin>>x;
		int l=0,r=n-1;//左右边界是左右下标
		while(l<r){
			int mid=(l+r)/2;
			if(a[mid]>=x)r=mid;//因为最后包含x这个边界,所以判断条件是>=x
			else l=mid+1;
		}
		if(a[l]==x){//当找到边界时等于就有不等于就没有
			printf("YES\n");
		}else printf("NO\n");

例题:

蒜头君手上有个长度为 nn 的数组 AA。由于数组实在太大了,所以蒜头君也不知道数组里面有什么数字,所以蒜头君会经常询问整数 xx 是否在数组 AA 中。

输入格式

第一行输入两个整数 nn 和 mm,分别表示数组的长度和查询的次数。

接下来一行有 nn 个整数 a_iai​。

接下来 mm 行,每行有 11 个整数 xx,表示蒜头君询问的整数。

输出格式

对于每次查询,如果可以找到,输出"YES",否则输出"NO"

数据范围

1 \le n, m \le 10^5, 0 \le x \le 10^61≤n,m≤105,0≤x≤106。

Sample 1

InputcopyOutputcopy
10 5
1 1 1 2 3 5 5 7 8 9
0
1
4
9
10
NO
YES
NO
YES
:NO

 答案:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
int a[100005];
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)cin>>a[i];
	sort(a,a+n);
	while(m--){
		int x;
		cin>>x;
		int l=0,r=n-1;
		while(l<r){
			int mid=(l+r)/2;
			if(a[mid]>=x)r=mid;
			else l=mid+1;
		}
		if(a[l]==x){
			printf("YES\n");
		}else printf("NO\n");
	}
	return 0;
}

 当找的数是浮点数的时候,我们这时的l,r,mid都应该是double类型,所以就不能用while(l<r)这个条件了,因为算出来的mid是小数点,所以我们需要规定如果r-l<1e-6那么我们就可以认为他们非常近了,就可以输出了,所以把条件改为while(r-l>1e-6),代码如下:

while(r-l>=1e-6){
    	double mid=(l+r)/2;
    	if(mid>=x){
    		r=mid;
		}else l=mid;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值