双指针算法

双指针算法

双指针算法的核心思想就是优化,主要是优化时间复杂度,可以将朴素算法优化至O(n)的时间复杂度。

最长连续不重复子序列
题意大致是给你一串序列,让你求它的最长连续不包含不重复字符的子序列的长度。

这是一道双指针算法的模板题。

首先是用i来从0n - 1的枚举,用来j表示距离i最左边的位置,使得i和j之间的子序列没有重复数字,显然i <= j。当i枚举到n - 1后,就可以得到res了。

其次,i和j之间具有单调性,即当i增加一位的时候,j不增加或者增加,不可能减小。当i增加一位时,序列中可能会出现重复字符。如果出现重复字符,必定是i指向的字符出现了重复,此时j往后移,直至i指向的字符不再重复出现。

我们用st[ ]数组存储每个字符出现的次数,当st[i] > 1时,说明这个字符重复出现了。

举个例子如下:
具体代码如下:

//当i确定时,j最多往左到什么地方,得满足中间序列没有重复元素
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int n, res;
int num[N], st[N];       //st记录区间内数据出现的次数

int main()
{
    cin >> n;
    for(int i = 0; i < n; i ++)
        cin >> num[i];
    
    for(int i = 0, j = 0; j < n; j ++)
    {
        st[num[j]] ++;            //一进入区间就给它出现的次数加一
        while(i <= j && st[num[j]] > 1)    //这里的i <= j可以不用写,因为i必定小于等于j
        {
            st[num[i]] --;                 //离开区间就给它出现的次数减一
            i ++;                          //离开区间 
        }
        res = max(res, j - i + 1);         //更新res的值
    }
    
    cout << res << endl;
    
    return 0;
}

数组元素的目标和

题意:两组数(a[N], b[N]),从中分别选一个数相加等于一个规定的常数x

这道题也挺简单,也是模板题。
使用两个指针i和j,i从头到尾遍历a数组,j从尾到头遍历b数组。
如果a[i] + b[j] > x,说明b[j]大了,得j --
如果a[i] + b[j] < x,说明a[i]小了,得i ++
如果相等,就直接输出。然后i ++,进行下一轮匹配。

举个例子如下:
在这里插入图片描述
具体见代码:

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int n, m, x;
int a[N], b[N];

int main()
{
    cin >> n >> m >> x;
    for(int i = 0; i < n; i ++)
        scanf("%d", & a[i]);
    for(int j = 0; j < m; j ++)
        scanf("%d", & b[j]);
    
    for(int i = 0, j = m - 1; i < n && j >= 0; i ++)
    {
        while(a[i] + b[j] > x)       //大于
            j --;
        
        if(a[i] + b[j] < x)          //小于
            continue;
        
        printf("%d %d\n", i, j);     //这里不用判断条件,因为能走到这里肯定是相等的
        j --;
    }
    
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值