算法思想: 利用问题本身与序列的特性(序列递增性质),使用两个下标i、j对序列进行扫描 (可以同向扫描,也可以反向扫描) ,以较低的复杂度解决问题。
TIPS:要注意双指针的方向选择!!!
eg1. 给定一个递增的正整数序列和一个正整数M,求序列中不同位置的数a和b,是的它们的和恰好为M,输出所有满足条件的方案。
// 两个指针反向扫描
while(i < j)
{
if(a[i]+a[j] == M)
{
printf("%d %d\n", i, j);
i++; // 如果只需要第一个解,直接break即可。
j--;
}
else if(a[i]+a[j] < M)
{
i++;
}
else
{
j--;
}
}
eg2. 序列合并问题
// 两个指针同向扫描
int merge(int A[], int B[], int C[], int n, int m)
{
int i = 0, j = 0, index = 0;
while(i<n && j<m)
{
if(A[i] <= B[j])
{
C[index++] = A[i++];
}
else
{
C[index++] = B[j++];
}
}
while(i < n)
{
C[index++] = A[i++];
}
while(j < m)
{
C[index++] = B[j++];
}
return index; // 返回序列C的长度
}
本题可以用二分法,也可以使用双指针算法。
双指针算法: 当m1较小时,与其对应的M1也相对较小;当m2较大时,与其对应的M2也相对较大。即m1 eg.4 PAT A1029 Median 仿照数组合并的思路,但此处不需要真的将合并数组存下来,只需要利用i、j两个指针的移动,移到中值所在位置即可。 此处可利用一个小技巧:将数组后边都加上一个最大值INF,这样便不需要再额外判断某个数组中的值是否已经全部取完。代码(AC):
#include
思路分析:
代码(未AC):
#include