找硬币题解 【哈希及双指针】

找硬币

伊娃喜欢从整个宇宙中收集硬币。

有一天,她去了一家宇宙购物中心购物,结账时可以使用各种硬币付款。

但是,有一个特殊的付款要求:每张帐单,她只能使用恰好两个硬币来准确的支付消费金额。

给定她拥有的所有硬币的面额,请你帮她确定对于给定的金额,她是否可以找到两个硬币来支付。

输入格式
第一行包含两个整数 N 和 M,分别表示硬币数量以及需要支付的金额。

第二行包含 N 个整数,表示每个硬币的面额。

输出格式
输出一行,包含两个整数 V1,V2,表示所选的两个硬币的面额,使得 V1≤V2 并且 V1+V2=M。

如果答案不唯一,则输出 V1 最小的解。

如果无解,则输出 No Solution。

数据范围
1≤N≤105,
1≤M≤1000
输入样例1:

8 15
1 2 8 7 2 4 11 15

输出样例1:

4 11

输入样例2:

7 14
1 8 7 2 4 11 15

输出样例2:

No Solution

分析

通过对N大小的观察我们可以推测出对于这一题来说时间复杂度应该是O(NlogN)或者O(N),对于O(N)的做法我选用的是哈希来做,而对于O(NlogN)的做法就用双指针算法,对于算法这里就不再介绍了,都在注释中!!

算法一 哈希 O(N)

#include<iostream>
#include<algorithm>
#include<unordered_set>
using namespace std;
int n, m;
unordered_set<int>hash1;
int main() {
	cin >> n >> m;
	int v1 = 10000,v2 = -1;//v1选用一个一定不存在的数
	for (int i = 0; i < n; i++) {
		int a, b;
		cin >> a;
		b = m - a;
		//假如b存在
		if (hash1.count(b)) {
			hash1.insert(a);
			if (a > b)swap(a, b);  //由于我们是以v1为基准判断最小的数,所以要进行判断和交换
			if (a < v1)v1 = a, v2 = b;  //如果当前方案中的最小数小于v1那么就更新
		}
		else {
			hash1.insert(a);
		}
	}
	if (v1 == 10000)puts("No Solution");
	else cout << v1 << " "<<v2 << endl;

	return 0;
}

在这里插入图片描述

算法二 双指针 O(NlogN)

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int N = 100010;
int n, m;
int w[N];
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		cin >> w[i];
	}
	sort(w, w + n); //排序
	for (int i = 0, j = n - 1; i < j;i++) {
		while (i<j&&w[i] + w[j]>m)j--;  //我们要把w[i]+w[j]>m的结果全部排除
		if (i<j&&w[i] + w[j]==m) {  //i<j是用于判断i和j是否处于一个位置
			cout << w[i] << " " << w[j];
			return 0;
		}
	}
	cout << "No Solution" << endl;
	return 0;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值