排序后使用左右指针寻找和为目标值的数对。
OJ: noi_openjudge
题目 ID: ch0111-07
难度:普及-
标签:排序双指针python
日期: 2026-07-30 23:01
题意
在整数序列中找一对数使其和为给定值;有多组时输出较小数最小的一组。
思路
先升序排序。左右指针的和偏小时左指针右移,偏大时右指针左移;相等时直接输出。左指针从最小数开始推进,因此第一次找到的数对具有最小的较小数。
代码
Python代码
python
input()
numbers = sorted(map(int, input().split()))
target_sum = int(input())
left, right = 0, len(numbers) - 1
while left < right:
current_sum = numbers[left] + numbers[right]
if current_sum == target_sum:
print(numbers[left], numbers[right])
break
if current_sum < target_sum:
left += 1
else:
right -= 1
else:
print("No")C++代码
cpp
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n,sum;
ll a[100005];
void init(){
scanf("%lld",&n);
int i;
for (i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
scanf("%lld",&sum);
}
//查找范围是[l,r), a[r] 永远 >= key
template <typename T>
int first_ge(T key,T a[],int l,int r){
int m;
while( l != r ) //表示l和r没有重合
{
m = (l+r) >>1; // 取中间位置
if( a[m] < key ) //表示 [m+1,r) 满足条件
l = m+1;
else
r = m;
}
return l;
}
int main(){
init();
sort(a+1,a+n+1);
int i;
for(i=1;i<=n;i++){
ll ret = sum - a[i];
int pos = first_ge(ret,a,i+1,n+1);
if( a[pos] == ret){
printf("%lld %lld\n",a[i],a[pos]);
return 0;
}
}
printf("No");
return 0;
}复杂度
排序为
总结
有序序列中的两数之和可通过一增一减的双指针在线性时间内完成。