Find Coins
Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special requirement of the payment: for each bill, she could only use exactly two coins to pay the exact amount. Since she has as many as 105 coins with her, she definitely needs your help. You are supposed to tell her, for any given amount of money, whether or not she can find two coins to pay for it.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive numbers: N (<= 1 0 5 10^5 105, the total number of coins) and M(<= 1 0 3 10^3 103, the amount of money Eva has to pay). The second line contains N face values of the coins, which are all positive numbers no more than 500. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print in one line the two face values V1 and V2 (separated by a space) such that V1 + V2 = M and V1 <= V2. If such a solution is not unique, output the one with the smallest V1. If there is no solution, output “No Solution” instead.
Sample Input 1:
8 15
1 2 8 7 2 4 11 15
Sample Output 1:
4 11
Sample Input 2:
7 14
1 8 7 2 4 11 15
Sample Output 2:
No Solution
题意
给出n个整数和一个指定的和m,从n个整数中选取两个数,使其和正好为m,从小到大输出这两个数,若存在多种组合,则输出第一个数最小的组合;若不存在这样的组合,则输出“No Solution”。
思路
n的范围决定了使用暴力枚举法很可能会超时,又看到是求两个数之和,很容易就想到要运用two pointers思想:首先将数字序列a进行排序,用两指针i, j分别指向序列的起始元素和末尾元素,如果a[i] + a[j] = m,则满足条件直接输出;如果a[i] + a[j] > m,由递增性可知,只有让j指针向左移动才有可能使和为m;同样的,如果a[i] + a[j] < m,则只有让i指针向右移动才有可能使和为m。当 i = j 时,说明不存在满足条件的组合。
下面介绍另一种基于hash的算法:建立hash表coin以判断当前面值的硬币是否出现过,每次读入一个数x,就判断m - y是否出现过,若出现过则配对成功。注意要选取x最小的一组。
代码实现
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
bool findSolution(vector<int> coin, int total)
{
int i = 0, j = coin.size() - 1;
while (i < j)
{
if (coin[i] + coin[j] < total) // i向右移动
i++;
else if (coin[i] + coin[j] > total) // j向左移动
j--;
else // 满足条件进行输出
{
printf("%d %d", coin[i], coin[j]);
return true;
}
}
return false; // 不存在满足条件的组合
}
int main()
{
vector<int> coin;
int n, total;
int x;
scanf("%d %d", &n, &total);
for (int i = 0; i < n; i++)
{
scanf("%d", &x);
coin.push_back(x);
}
sort(coin.begin(), coin.end()); // 有序排列是必要条件
bool flag = findSolution(coin, total);
if (!flag)
printf("No Solution");
return 0;
}
代码实现——hash
#include <cstdio>
using namespace std;
bool coin[501];
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int n, m;
int x, y;
int minx = 501, miny;
bool flag = false; // flag判断是否存在满足条件的解
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf("%d", &x);
y = m - x;
if (coin[y] && y > 0 && y <= 500)
{
if (x > y) // 使x最小以便于判断
swap(x, y);
if (x < minx)
{
minx = x;
miny = y;
flag = true;
}
}
coin[x] = true; // 注意该步必须放在循环的末尾,不然当 x = y 时可能出现问题
}
if (flag)
printf("%d %d", minx, miny);
else
printf("No Solution");
return 0;
}
参考