two pointers入门

two Pointers入门

给定一个递增序列

A[6] = {1,2,3,4,5,6};

求序列中两个任意元素下标 i 和 j ,令这两个元素的和为某个特定的值m
正常做只需用两重for循环遍历该数组求和然后输出结果即可

for(int i = 0; i < n; i++)
{
	for(int j = i+1 ; j < n; j++)
	{
		if(A[i] + A[j] == m)
			printf("%d", i , j);
	}
 
}

算法时间复杂度为O(n2)

当n = 10 5甚至更多时该方法必然会相当的慢

通过仔细思考,我们可以发现:

  1. 当A[i] + A[j] >m时, 一定有A[i] + A[j+1]> m,所以 j+1到n-1的遍历都是无效遍历
  2. 当A[i] + A[j] >m时,一定有A[i+1] + A[j]> m,所以 i+1到n-1的遍历都是无效遍历

提示:该数组A为递增数组,且为一维数组,不懂的可以随便取个数m在纸上画一画A的遍历过程即可

我们将 i 设在起始位置 0 ,j 设为末尾位置 n-1:
1 A[i] + A[j] == m时, A[ i + 1] +A[ j ] > m 且 A[ i ] +A[ j- 1] < m
但A[ i + 1] + A[ j - 1 ]与m的大小关系是什么呢?我们已经知道前面控制一个变量增减时m的情况,此时两个变量都发生了变化,我们无法知晓他们之间的大小关系,是 > < 或是=呢? 我们可以把[ i + 1] 和 [ j - 1 ]设为下一个待定范围
2. A[i] + A[j] > m时, 有A[ i + 1 ] + A[ j ] > m恒成立,但 A[ i ] +A[ j- 1] 与m的关系我们不知道,所以将 范围缩小到 [ i, j-1 ]
3. A[i] + A[j] < m时, A[ i ] +A[ j- 1] < m恒成立,同样我们不知道A[ i + 1 ] + A[ j ]与m的大小关系,此时把范围缩小到[ i + 1, j ]

不懂的建议继续草稿纸上画一下

我这里是把 i 变成了left, j变成了 right

#include <iostream>
#include<cstdio>
using namespace std;

int A[6] = {1,2,3,4,5,6};
const int arrayLen = 5;
int twoPointers(int m)
{
    int left = 0, right = arrayLen;
    while(left<= right)
    {
        if(A[left] + A[right] == m)
        {
            printf("%d %d\n", A[left], A[right]);
            left++;right--;
        }
        else if(A[left] + A[right] < m)
        {
            left++;
        }
        else
        {
            right--;
        }
    }
}

int main()
{
    int m = 5;
    twoPointers(m);
    return 0;
}

算法时间复杂度为O(n)

序列合并问题

假设有两个递增序列A和B,要求将他们合并为一个递增序列C

做法:
分别设置两个下标i j 在A和B中
A[ i ] > B[ j ]时,将B[ j ]放入序列C中
A[ i ] < B[ j ]时,将A[ i ]放入序列C中
A[ i ] == B[ j ]时,将A[ i ]或B[ j ]放入序列C中
当 i 或 j 达到末尾时就把另外一个数组其余部分放进C中

上代码

 int A[6] = {1,3,4,5,7,9};
 int B[7] = {1,2,4,6,8,10, 12};
 int C[13];
void append()
{
    int i = 0, j = 0;
    int k = 0;
    while(i < 6 && j < 7)
    {
        if(A[i] > B[j])
            C[k++] = B[j++];
        else
            C[k++] = A[i++];
    }
    while(i < 6) C[k++] = A[i++];
    while(j < 7) C[k++] = B[j++];
    for(int i = 0; i< 13; i++)
        printf("%d ", C[i]);
}

练习题

完美数列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值