C程序 双指针技术
双指针确实是一种简单而有效的技术,通常用于搜索排序数组中的配对。
给定一个有N个整数的排序数组A(按升序排序),求是否存在任何一对元素(A[i], A[j]),使其总和等于X。
让我们看看这个原生的解决方案。
// Naive solution to find if there is a
// pair in A[0..N-1] with given sum.
#include <stdio.h>
int isPairSum(int A[],int N,int X)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
{
// as equal i and j means same element
if (i == j)
continue;
// pair exists
if (A[i] + A[j] == X)
return true;
// as the array is sorted
if (A[i] + A[j] > X)
break;
}
}
// No pair found with given sum.
return 0;
}
// Driver Code
int main()
{
int arr[]={3,5,9,2,8,10,11};
int val=17;
int arrSize = sizeof(arr)/sizeof(arr[0]);
// Function call
printf("%d",isPairSum(arr,arrSize,val));
return 0;
}
输出
1
时间复杂度: O(n 2)。
现在我们来看看双指针技术是如何工作的。我们取两个指针,一个代表数组的第一个元素,另一个代表数组的最后一个元素,然后我们将两个指针上的值相加。如果它们的总和小于X,那么我们就把左边的指针移到右边,如果它们的总和大于X,那么我们就把右边的指针移到左边,以便更接近总和。我们继续移动指针,直到我们得到的总和为X。
#include <stdio.h>
// Two pointer technique based solution to find
// if there is a pair in A[0..N-1] with a given sum.
int isPairSum(int A[], int N, int X)
{
// represents first pointer
int i = 0;
// represents second pointer
int j = N - 1;
while (i < j)
{
// If we find a pair
if (A[i] + A[j] == X)
return 1;
// If sum of elements at current
// pointers is less, we move towards
// higher values by doing i++
else if (A[i] + A[j] < X)
i++;
// If sum of elements at current
// pointers is more, we move towards
// lower values by doing j--
else
j--;
}
return 0;
}
// Driver code
int main()
{
// array declaration
int arr[] = { 3, 5, 9, 2, 8, 10, 11 };
// value to search
int val = 17;
// size of the array
int arrSize = sizeof(arr) / sizeof(arr[0]);
// Function call
printf("%d", isPairSum(arr, arrSize, val));
return 0;
}
输出
1
插图:
时间复杂度: O(n)
这是如何做到的?
该算法基本上利用了输入数组被排序的事实。我们从极端值(最小和最大)的总和开始,有条件地移动两个指针。当A[i]和A[j]的总和小于X时,我们就移动左边的指针i,我们不会错过任何一对,因为总和已经小于X。
更多基于双指针技术的问题。
- 从两个排序的数组中找出最接近的一对
- 在数组中找出总和最接近于x的一对。
- 找到所有和为零的三联体
- 找到与给定值相加的三联体
- 找到一个三联体,使两个元素之和等于第三个元素
- 找到四个元素的总和为给定值