有一天,她去了一家宇宙购物中心购物,结账时可以使用各种硬币付款。
但是,有一个特殊的付款要求:每张帐单,她只能使用恰好两个硬币来准确的支付消费金额。
给定她拥有的所有硬币的面额,请你帮她确定对于给定的金额,她是否可以找到两个硬币来支付。
输入格式
第一行包含两个整数 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
①二分做法:
先对原给出的硬币面额从大到小排序,再二分找出满足条件的即可
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int arr[100005];
int main(void)
{
int n, m, i;
int k = 0;
cin >> n >> m;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
sort(arr, arr + n);
for (i = 0; i < n; i++)
{ //注意二分查找的起始位置,要从arr[i]的下一个位置开始。
int c = lower_bound(arr + i + 1, arr + n, m - arr[i]) - arr;
if (arr[c] + arr[i] == m) {
cout << arr[i] << ' ' << arr[c] << endl;
break;
}
}
/*while (left < right)//手写二分
{
int mid = right + left>>1;
if (arr[mid] >= m - arr[i])right = mid;
else left = mid + 1;
}
if (arr[i] + arr[left] == m) {
cout << arr[i] << ' ' << arr[left] << endl;
break;
}*/
if (i == n)cout << "No Solution";
return 0;
}
②哈希表(时间复杂度On)的做法
#include <iostream>
#include <algorithm>
#include <unordered_set>//hash的容器
#include<cstdio>
using namespace std;
int arr[100005];
int main(void)
{
int n, m;
int a, b;
int v1 = 100001, v2;
unordered_set<int>hash;
cin >> n >> m;
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
int temp = m - arr[i];
if (hash.count(temp))//如果temp的数量不为0.表明找到一组解
{
hash.insert(arr[i]);//首先将arr[i],添加到表里面
a = arr[i],b = temp;
if (a > b)swap(a,b);//保证a<b,也就是v1<v2
if (a < v1)v1 = a, v2 = b;//找到v1最小的一组解
}
else {//无论是否找到一组解,都要把arr[i]添加到hash里面
hash.insert(arr[i]);
}
}
if (v1 != 100001)cout << v1 << ' ' << v2 << endl;
else cout << "No Solution" << endl;
return 0;
}
③双指针的做法(时间复杂度O(nlogn))
首先需要对这一串序列保证单调有序,设置头指针 i ,位指针 j 。然后从小到大枚举arr[i],如果arr[i]+arr[j]>m,由于arr[i]是最小的且序列单调,所以arr[i+1]不可能和arr[j]组成一组解,此时就要j- -。如果arr[i]+arr[j]<m了,那么arr[j-1]必然不可能和arr[i],组成一组解,此时就要i++。如果arr[i]+arr[j]=m,因为序列从小到大,所以此时答案就找到了,就是arr[i]和arr[j]
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int arr[100005];
int main(void)
{
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++)scanf("%d", &arr[i]);
sort(arr, arr + n);
int j = n - 1;
for (int i = 0; i < n,i<j; i++)
{ //注意 i<j 的条件。
while (i<j&&arr[i] + arr[j] > m)j--;
if (i<j&&arr[i] + arr[j] == m)
{
cout << arr[i] << ' ' << arr[j] << endl;
return 0;
}
}
cout << "No Sulution";
return 0;
}