$\Huge\color{orchid}{点击此处获取更多干货}$
双指针
这个问题的解决方式比较多样:
1. 最简单的办法是枚举序列A中的每一个元素$a$,然后找到序列B中的元素$b=x-a$,由于两序列都是升序的,因此可以二分查找,时间复杂度为$O(n*logn)$,空间复杂度为$O(1)$;
2. 还可以把序列A中的每个元素存入哈希表,然后枚举序列B中的每一个元素,查找$x-b$是否在哈希表中,时空间复杂度都为$O(n)$;
3. 接下来着重介绍双指针法,时间复杂度同样为$O(n)$,但是空间复杂度仅$O(1)$。
条件$a_i+b_i==x$可以分为两半来看
1. $a+b_i\le x$:序列A中元素已确定,当某个$b_i$满足了条件1时,可以确定序列B从$i+1$位开始的后缀中,每个元素都不满足条件1,i只有继续减少才可能继续满足;
2. $a_i+b\ge x$:序列B中元素已确定,当某个$a_i$满足条件2时,序列A在以$i-1$位为末端的前缀中,每个元素都不满足条件2,i只能继续增加才可能继续满足;
因此,初始化双指针$(i,j)$索引对时,$i$指向序列A的头端,$j$指向序列B的尾端(也可以反过来)。当$i$和$j$都没有越界时,每次循环检查$a_i+b_j$是否等于目标和$x$,偏大则减少$j$,偏小则增加$i$,直到相等(一定存在)
C++ 代码
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m, x;
cin >> n >> m >> x;
int* a = new int[n], * b = new int[m];
for(int i = 0; i < n; i++) {
cin >> a[i];
}
for(int i = 0; i < m; i++) {
cin >> b[i];
}
int i = 0, j = m - 1;
while(i < n && j >= 0) {
if(a[i] + b[j] == x) {
cout << i << " " << j << endl;
return 0;
}
else if(a[i] + b[j] > x) {
j--;
}
else {
i++;
}
}
delete[] a;
delete[] b;
return 0;
}