返回目录
题意
给出n个正整数和一个正整数m, 间n个数字中是否存在一对数字a和b(a≤b), 使得a+b=m成立。如果有多对,输出a最小的那一对。
样例(可复制)
8 15
1 2 8 7 2 4 11 15
样例输出
4 11
注意点
- 本题提供3种解决办法:散列法、二分法和two pointers
- 使用散列法时:map的大小不需要很大,也不能像500这么小,比1000大点就好了,如果map只开到500这么大,那map[m-i]会发生越界,测试点报段错误
- 使用二分法时:找到第一个大于等于m-num[i]位置j时,要判断当前的j是否就是i,如果是,需要跳过这种情况
散列法
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,m,map[1010]={0};
cin>>n>>m;
while(n--){
int tmp;
scanf("%d",&tmp);
if(tmp>m)continue;
map[tmp]++;
}
int i;
for(i=1;i<1000;i++){
if(2*i==m&&map[i]>=2){
cout<<i<<" "<<m-i;break;
}
if(map[i]&&map[m-i]&&2*i!=m){
cout<<i<<" "<<m-i;break;
}
}
if(i==1000)cout<<"No Solution";
return 0;
}
二分法
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
int num[100010];
for(int i=0;i<n;i++)scanf("%d",&num[i]);
sort(num,num+n);
int i;
for(i=0;i<n;i++){
int j=lower_bound(num,num+n,m-num[i])-num;
if(i==j)continue;
if(num[i]+num[j]==m){
cout<<num[i]<<" "<<num[j];break;
}
}
if(i==n)cout<<"No Solution";
return 0;
}
two pointers
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
int num[100010];
for(int i=0;i<n;i++)scanf("%d",&num[i]);
sort(num,num+n);
int i=0,j=n-1;
while(i<j){
if(num[i]+num[j]==m){
cout<<num[i]<<" "<<num[j];
return 0;
}
if(num[i]+num[j]>m)j--;
else if(num[i]+num[j]<m)i++;
}
cout<<"No Solution";
return 0;
}