题解:AcWing 800 数组元素的目标和
【题目来源】
AcWing:800 数组元素的目标和 - AcWing题库
【题目描述】
给定两个升序排序的有序数组 \(A\) 和 \(B\),以及一个目标值 \(x\)。
数组下标从 \(0\) 开始。
请你求出满足 \(A[i]+B[j]=x\) 的数对 \((i,j)\)。
数据保证有唯一解。
【输入】
第一行包含三个整数 \(n,m,x\),分别表示 \(A\) 的长度,\(B\) 的长度以及目标值 \(x\)。
第二行包含 \(n\) 个整数,表示数组 \(A\)。
第三行包含 \(m\) 个整数,表示数组 \(B\)。
【输出】
共一行,包含两个整数 \(i\) 和 \(j\)。
【输入样例】
4 5 6
1 2 4 7
3 4 6 8 9
【输出样例】
1 1
【核心思想】
-
问题分析:给定两个已按升序排列的数组 \(A\)(长度 \(n\))和 \(B\)(长度 \(m\)),以及目标和 \(x\),需要找到满足 \(A[i] + B[j] = x\) 的唯一数对 \((i, j)\)。这是一个双指针(对撞指针)问题,关键在于如何利用数组的有序性高效查找。
-
算法选择:
- 双指针(对撞指针):一个指针 \(i\) 从数组 \(A\) 的起始位置(\(0\))向右移动,另一个指针 \(j\) 从数组 \(B\) 的末尾位置(\(m-1\))向左移动
- 单调性利用:由于 \(A\) 升序、\(B\) 升序,当 \(A[i]\) 增大时,需要 \(B[j]\) 减小才能保持和为 \(x\)
-
关键步骤:
- 初始化:\(i = 0\)(指向 \(A\) 的起始),\(j = m - 1\)(指向 \(B\) 的末尾)
- 遍历数组 \(A\)(\(i\) 从 \(0\) 到 \(n-1\)):
- 调整指针 \(j\):当
a[i] + b[j] > x时,说明 \(B[j]\) 太大,需要 \(j\) 左移寻找更小的 \(B[j]\) - 检查条件:如果
a[i] + b[j] == x,找到答案,输出 \((i, j)\) 并结束
- 调整指针 \(j\):当
- 由于数据保证有唯一解,一定能找到答案
-
时间/空间复杂度:
- 时间复杂度:\(O(n + m)\),\(i\) 最多遍历 \(n\) 次,\(j\) 最多左移 \(m\) 次
- 空间复杂度:\(O(1)\),只使用了两个指针
-
双指针(对撞指针)的核心思想:
- 单调性利用:数组 \(A\) 递增、数组 \(B\) 递增,当 \(A[i]\) 增大时,\(B[j]\) 必须减小才能使和保持为 \(x\)
- 对撞策略:一个指针从头开始,一个从尾开始,相向而行
- 避免枚举:不需要枚举所有 \(n \times m\) 个数对,利用单调性将复杂度从 \(O(nm)\) 降到 \(O(n+m)\)
- 贪心正确性:对于当前的 \(A[i]\),找到最大的 \(B[j]\) 使得 \(A[i] + B[j] \leq x\),如果等于则找到答案,如果小于则 \(i\) 右移(因为更大的 \(A[i]\) 需要更小的 \(B[j]\))
- 适用于两数组之和等于目标值、两数之和类问题
【解题思路】

【算法标签】
双指针
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 100010; // 定义数组最大长度
int n, m, x; // n: 数组a的长度, m: 数组b的长度, x: 目标和
int a[N], b[N]; // 两个待处理的数组
int main()
{
// 输入数组a的长度、数组b的长度和目标和x
scanf("%d%d%d", &n, &m, &x);
// 输入数组a的元素
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
// 输入数组b的元素
for (int i = 0; i < m; i++)
{
scanf("%d", &b[i]);
}
// 双指针算法:i从数组a的起始位置开始,j从数组b的末尾开始
for (int i = 0, j = m - 1; i < n; i++)
{
// 当两数之和大于x时,移动j指针向左寻找更小的数
while (j >= 0 && a[i] + b[j] > x)
{
j--;
}
// 找到满足条件的数对
if (a[i] + b[j] == x)
{
printf("%d %d\n", i, j); // 输出下标
break; // 找到后立即退出
}
}
return 0;
}
【运行结果】
4 5 6
1 2 4 7
3 4 6 8 9
1 1
浙公网安备 33010602011771号