双指针算法

常见分类

一、两个指针指向两个序列

对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

例如:归并排序

二、两个指针指向一个序列

对于一个序列,用两个指针维护一段区间

例如:快速排序

通用模板

for(i = 0,j = 0; i < n; i ++ )

{

      while(j < i && check(i,j) j ++ ;  //j在合法的范围并且满足某种性质

     //每道题目的具体逻辑

}

 核心思想

for(int i = 0; i < n; i ++ )

    for(int j = 0; j < n; j ++ )

        O(n^2)    

将上面的朴素算法优化到O(n)

举个“栗子”^-^

双指针算法的一个简单应用,方便理解一下模板的使用

读入连续的字符串,以此输出字符串中的每个单词

#include <iostream>
#include <string.h>

using namespace std;

int main()
{
    char str[1000];

    //gets(str);   
    fgets(str, N, stdin);

    int n = strlen(str);

    for(int i = 0; i < n; i ++ )
    {
        int  j = i;
        while(j < n && str[j] != ' ') j ++ ;

        //这道题的具体逻辑
        for(int k = i; k < j; k ++ )
        cout << str[k];
        cout << endl;

        i = j;
    }
    return 0;
}

//输入 abc def gh
//输出 abc
//    def
//    gh

注:gets()在c++14中已被删除

fgets()用法可参考:fgets函数及其用法,C语言fgets函数详解-CSDN博客

 典例1——最长连续不重复子序列

朴素做法:O(n^2)

for(int i = 0; i < n; i ++ )

        for(int j = 0; j <= i; j ++ )

            if(check(j,j))

            {

                res = max(res,i - j + 1);

            } 

双指针算法:O(n)

for(int i = 0; i < n; i ++ )

    {

        while(j <= i && check(j,i))

        res = max(res,i - j + 1);

    }

#include <iostream>

using namespace std;

const int N = 100010;

int n;
int a[N],s[N];

int main()
{
    cin >> n;
    for(int i = 0; i < n; i ++ )
    cin >> a[i];
    
    int res = 0;
    for(int i = 0,j = 0; i < n; i ++ )
    {
        s[a[i]] ++ ; //记录数组a中元素出现次数
        while(s[a[i]] > 1) //有重复元素出现
        {
            s[a[j]] -- ;  //将j指针后移找到新的无重复元素的区间
            j ++ ; 
        }
        res = max(res,i - j + 1);
    }
    
    cout << res;
    return 0;
}

🐖:while (j < i && s[q[i]] > 1) s[q[j ++ ]] – ; 里可以不加 j<i 的原因:因为当j > i时,所有s[]必然是0,此时循环中的第二个条件一定不成立。 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值