PAT A1048 Find Coins
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
-
思路 1:
hash表法,每输入一个数x,就用has[x]++,记录这个数出现了几次,因为输出要求取v1最小,故可以先从小到大排序,然后从头开始遍历,判断每个数对应的“补数”是否“存在”,因为有重复输入的情况,所以每次判断前,都要先把对应的has[]– -
code 1:
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 100020;
int value[maxn];
int has[1110] = {0}; //不能只开500->因为后面m-value[i]可能>500
int main(){
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i){
scanf("%d", &value[i]);
has[value[i]]++;
}
sort(value, value+n);
int ans = -1;
for(int i = 0; i < n; ++i){
has[value[i]]--; //先取出
if(has[m - value[i]] > 0){ //再判断是否还有
ans = value[i];
break;
}
}
if(ans == -1) printf("No Solution");
else printf("%d %d", ans, m - ans);
return 0;
}
-
思路 2:
Two-Point法,注意边界 -
code 2:
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 100020;
int value[maxn];
int main(){
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i){
scanf("%d", &value[i]);
}
sort(value, value+n);
int left = 0, right = n-1;
//!!!:Wrong 1:防止right和left越界 数据: 4 4 4 4 6, m = 4 每个while都加一个边界限制
while(value[left] + value[right] > m && right > left){
right--;
}
while(value[left] + value[right] < m && left < right){
left++;
}
//!!!:Wrong 2:必须同时保证 left和right没指同一个元素 数据:1 4 10 11 11 13,m = 8,结果会是4 4
if(value[left] + value[right] == m && left != right){
printf("%d %d", value[left], value[right]);
}else{
printf("No Solution");
}
return 0;
}
- code 2-2: 优化!从两端不断向中间缩小范围
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 100020;
int value[maxn];
int main(){
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i){
scanf("%d", &value[i]);
}
sort(value, value+n);
int left = 0, right = n-1;
while(left < right){
if(value[left] + value[right] == m){
printf("%d %d", value[left], value[right]);
break;
}else if(value[left] + value[right] < m) left++;
else right--;
}
if(left == right) printf("No Solution");
return 0;
}
-
思路 3:
二分法 -
code 3:
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 100020;
int value[maxn];
int BinSearch(int left, int right, int x){
while(left < right){
int mid = (left + right) / 2;
if(value[mid] == x) return mid;
else if(value[mid] > x) right = mid;
else left = mid + 1;
}
return -1; //没找到
}
int main(){
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i){
scanf("%d", &value[i]);
}
sort(value, value+n);
bool flag = true;
//遍历对每个元素,用二分查找后序中是否有"匹配"的(相加=m)
for(int i = 0; i < n; ++i){
int aim = m - value[i];
if(BinSearch(i+1, n, aim) != -1){
printf("%d %d", value[i], aim);
flag = false;
break;
}
}
if(flag) printf("No Solution");
return 0;
}
- code 3-2:其他几种查找区间不同的二分查找
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = 100020;
int value[maxn];
int BinSearch(int left, int right, int x){
while(left < right-1){
int mid = (left + right) / 2;
if(value[mid] > x) right = mid;
else left = mid;
}
return left;
}
int BinSearch2(int left, int right, int x){
while(left < right){
int mid = (left + right) / 2;
if(value[mid] < x) left = mid+1;
else right = mid;
}
return left;
}
int main(){
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i){
scanf("%d", &value[i]);
}
sort(value, value+n);
bool flag = true;
//遍历对每个元素,用二分查找后序中是否有"匹配"的(相加=m)
for(int i = 0; i < n-1; ++i){
//!!!:Wrong 1:边界条件为n-1,因为二分是在i后面的区间查找,如果后面的区间长度为0,就没意义了(必然不匹配)
int aim = m - value[i];
int pos = BinSearch(i+1, n, aim); //在区间[left, right)内查找
int pos2 = BinSearch2(i+1, n-1, aim); //在区间[left, right]内查找
if(value[pos] == aim){
printf("%d %d", value[i], aim);
flag = false;
break;
}
}
if(flag) printf("No Solution");
return 0;
}
-
思路: 无须排序,类似于:单身狗PAT A1121 Damn Single、危险品PAT A1149 Dangerous Goods Packaging,输入时就用Min记录最小V1
-
T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
bool has[maxn];
int main(){
int n, m, Min = maxn;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i){
int tmp;
scanf("%d", &tmp);
int d = m-tmp;
if(has[d] == true){
int t_min = min(d, tmp);
Min = min(t_min, Min);
}else has[tmp] = true;
}
if(Min == maxn) printf("No Solution");
else printf("%d %d", Min, m - Min);
return 0;
}
- T3 code:
#include <bits/stdc++.h>
using namespace std;
vector<int> seq;
int BinSearch(int x, int left, int right)
{
while(left < right)
{
int mid = (left + right) / 2;
if(seq[mid] == x)
{
return seq[mid];
}else if(seq[mid] < x)
{
left = mid + 1;
}else
{
right = mid;
}
}
return -1;
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
seq.resize(n);
for(int i = 0; i < n; ++i)
{
scanf("%d", &seq[i]);
}
sort(seq.begin(), seq.end());
for(int i = 0; i < n; ++i)
{
int right = BinSearch(m - seq[i], i + 1, n);
if(right != -1)
{
printf("%d %d", seq[i], right);
return 0;
}
}
printf("No Solution");
}
- T4 code:
#include <bits/stdc++.h>
using namespace std;
vector<int> num;
int BinSearch(int left, int right, int x)
{
while(left < right)
{
int mid = (left + right) / 2;
if(x == num[mid])
{
return mid;
}else if(x < num[mid])
{
right = mid;
}else
{
left = mid + 1;
}
}
return -1;
}
int main()
{
int n, aim;
scanf("%d %d", &n, &aim);
num.resize(n);
for(int i = 0; i < n; ++i) scanf("%d", &num[i]);
sort(num.begin(), num.end());
for(int i = 0; i < n; ++i)
{
int pos = BinSearch(i+1, n, aim - num[i]);
if(pos < 0) continue;
if(num[pos] + num[i] == aim)
{
printf("%d %d", num[i], num[pos]);
return 0;
}
}
printf("No Solution");
return 0;
}