首尾指针法多应用于在已排序的数组中实现O(N)的查找。
例如:给定一个整数k,对于两个递增数组,找到(i, j)使得 a 中的 i 位置与 b 中的 j 位置满足 a[i] + b[j] = k。
对于这种问题,我们往往可以取 a 中的第i位及 b 中第j位,依次相加并根据相加结果与数值 k 的大小来决定i, j的移动方向。
具体代码如下:
#!CPP
while (i < a.size()) {
while(a[i] + b[j] > X && j > 0) j--;
if (a[i] + b[j] == X) writeAnswer(i, j);
i++;
}
问题变形:
1、对于无重复元素的数组 a,问存在多少种三个数相加,和为定值k的情况。
解答:先对数组排序,外部循环遍历a,并在循环内部找a[p] + a[q] = k - a[i]的情况。其中 p,q 的寻找即利用首尾指针法。
2、对于无重复元素的数组 a,问存在多少种两个数相减,和为定值k的情况。
解答:先对数组排序,外部循环遍历a,判断a[i] + k是否在数组a中即可,判断可以利用set来实现log(N)的时间复杂度,因此该算法的时间复杂度为O(NlogN)。
解答: 更高效的方法是取i = 0, j = 1, 当 a[j] - a[i] > k 时,++i;当a[j] - a[i] < k时,++j;