题目大意:
给出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;
}