抽签 c++二分查找

【题目描述】:

将写有数字的n个纸片放入口袋,抽取四次,每次抽取后记下数字后放回纸片,判断这四个数字和是否有可能为m?

限制条件:

1<=n<=50

1<=m<=10(8)

1<=ki<=10(8)

【分析】:

因为是 4张,且是又放回抽取,假设数字是a,b,c,d;

因此前两次抽取的值的和的有可能的情况(a+b) 和 后两者抽取的值的和的情况(c+d)是一样的,那么做题思路就出来了:

先用一个二维数组记录出所有的两种数字组合的情况(相当于列举抽取的a+b的值)

再用m-(a+b)表示(c+d),在二维数组中找寻m-(a+b),如果存在(找得到),那么说明就可以为m,否则就说明这种情况不符合

查找的时候,先对二维数组排序,采用二分查找法,减少时间复杂度

总体:算法复杂度为n²log(n)

代码

#include<iostream>
#include<algorithm>
#define N 1000+5
using namespace std;
int n,m;
int a[N];
int b[N*N];//用一维数组 表达二维数组
bool search(int x) {
	int l=0,r=n*n-1;
	while(l<r) {
		int i=(l+r)/2;//二分查找
		if(b[i]==x)
			return true;
		if(b[i]<x)
			l=i+1;
		else
			r=i;
	}
	return false;
}
void solve() {
	for(int i=0; i<n; i++) { //行
		for(int j=0; j<n; j++) { //列
			b[i*n+j]=a[i]+a[j];//每个两个纸片的组合均计算包含了
		}
	}
	sort(b,b+N*N);//排序
	bool c=false;
	for(int i=0; i<n; i++) {
		for(int j=0; j<n; i++) {
			if(search(m-a[i]-a[j])) {//查找剩余的值是否出现在组合情况中
				c=true;
				break;
			}
		}
	}
	/*
	上述代码修改成这样也可以
	for(int i=0; i<n*n; i++) {
		if(search(m-b[i])) {
			c=true;
			break;
		}
	}
*/
	if(c==true)
		cout<<"yes"<<endl;
	else
		cout<<"no"<<endl;
}
int main() {
	cin>>n>>m;
	for(int i=0; i<n; i++)//输入卡片上的值
		cin>>a[i];
	solve();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MORE_77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值