[PAT-A 1048]Find Coins

在这里插入图片描述
在这里插入图片描述
题目大意:
给出n个正整数和一个正整数m。问n个数字中是否存在一对数字a和b(a<=b)使得a+b=m成立。
如果有多对,输出a最小的那一对,如果没有,输出No Solution.

思路1:Hash散列:
1)以int型HashTable[]数组存放每个数字出现的个数,其中HashTable[i]表示i出现的次数(1<=i<=1000)。
2)枚举1-1000中的每一个数字i,若i存在与数列,即HashTable[i]>0且m-i存在与数列即HashTable[m-i]>0,则找到了一对数,i,m-i,他们的和为m。
如果i==m-i时必须要保证i的个数要大于等于2,否则不行。
3)如果有多组答案,一定要输出最小的那一对。

AC代码:

//PAT_A 1048
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1005;
int HashTable[maxn];
int main() {
	int n, m, a;
	(void)scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++) {
		(void)scanf("%d", &a);
		HashTable[a]++;
	}
	for (int i = 1; i < n; i++) {//从最小的开始循环, 也保证了左右可能的结果中输出i最小的
		if (HashTable[i] && HashTable[m - i]) {
			if (i == m - i && HashTable[i] <= 1)continue;
			printf("%d %d\n", i, m - i);
			return 0;
		}
	}
	printf("No Solution\n");
	return 0;
}

思路2:二分查找:
1)令int型a[]数组存放读入的所有数,并在读入完毕后对a数组从小到大排序。
2)枚举a[0],a[1]…a[n-1],每个数组用二分法查找数组内是否存在m-a[i],如果是且下标不是i,则输出a[i]与m-a[i],如果枚举完成还没有发现匹配的一对,则输出No solution.

AC代码:

//PAT_A 1048
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100010];
int Bin(int left, int right, int key) {
	int mid;
	while (left <= right) {
		mid = (left + right) / 2;
		if (a[mid] == key)return mid;
		else if (a[mid] > key)right = mid - 1;
		else left = mid + 1;
	}
	return -1;
}
int main() {
	int i, n, m;
	bool flag = false;
	(void)scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++) {
		(void)scanf("%d", &a[i]);
	}
	sort(a, a + n);
	for (i = 0; i < n; i++) {
		int pos = Bin(0, n - 1, m - a[i]);
		if (pos != -1 && pos != i) {
			printf("%d %d\n", a[i], a[pos]);
			flag = true;
			break;
		}
	}
	if(flag == false)printf("No Solution");
	return 0;
}

思路三:tow pointers
1)先使用sort函数将序列从大到小排序.
2)定义两个下标i,j,初值分别为0,n-1,根据a[i]+a[j]与M的大小进行操作
1.若a[i]+a[j]==M 退出循环
2.若a[i]+a[j]<M i++
3.若a[i]+a[j]>M j–
上面的操作知道i>=j时结束,结束时根据i>=j是否成立来确定解是否存在

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int main() {
	int n, m, a[maxn];
	(void)scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++) {
		(void)scanf("%d", &a[i]);
	}
	sort(a, a + n);
	int i = 0, j = n - 1;
	while (i < j) {
		if (a[i] + a[j] == m)break;
		else if (a[i] + a[j] < m)i++;
		else j--;
	}
	if (i < j)printf("%d %d\n", a[i], a[j]);
	else printf("No Solution");
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值