• 双指针算法


    对于两重for循环

    for(int i = 0; i < n; ++i)
        for(int j = 0; j < n; ++j)
        {
            //具体代码
        }//O(n^2)
    

    双指针算法的思想就是:寻找指针i 与 j 之间是否有单调的关系。若存在,则利用此关系来把整个枚举的状态数量从O(n^2)降到O(n),模板如下

    for(int i = 0, j = 0; i < n; ++i)
    {
        while(j < i && check(j, i)) ++j;//此行为降低时间复杂度的关键。check()函数反映指针i与j的性质
    
        //每道题目的具体逻辑
    }
    

    最典型的应用如下:

    给你一个英文字符串,找到每一个单词并逐行输出

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    /**
     * 把一个字符串中的所有单词找到,并按行输出
     * */
    int main()
    {
        char str[100];
        gets(str);
        int n = strlen(str);
        for(int i = 0; i < n; ++i) cout << str[i];
        cout << '
    ';
        
        for(int i = 0; i < n; ++i)
        {
            int j = 0;
            while(j < i && str[j] != ' ') ++j;
            
            //双指针算法的具体逻辑部分
            for(int k = i; k < j; ++k)
                printf("%c", str[k]);
            cout << '
    ';
        }
    }
    

    当然了,往往会卡在这个j与i指针之间的关系并不好找
    最长连续不重复子序列
    给定一个长度为n的整数序列,请找出最长的不包含重复数字的连续区间,输出它的长度。

    输入格式
    第一行包含整数n。

    第二行包含n个整数(均在0~100000范围内),表示整数序列。

    输出格式
    共一行,包含一个整数,表示最长的不包含重复数字的连续子序列的长度。

    数据范围
    1≤n≤100000


    具体解题思路:运用桶排思想,用数组s[]来记录每个输入的数字a[i]出现的次数,当s[a[i]]出现的次数大于1时,[j, i]区间构成的子序列就必定有重复元素,因此我们只能通过右移j指针,来试图在[j, i]区间中找到这个重复的元素并将其排除(s[a[i]]--; ++j;)每次j指针右移我们都需要检查一下s[a[i]]是否已经等于1(数字a[i]是否仅在新的区间[j, i]中出现一次)来判断是否停止移动j指针

    具体代码如下

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    const int N = 100010;
    int n;
    int a[N], s[N];//桶排序思想,当数据范围过大时应该用哈希表来求解
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n;
        for(int i = 0; i < n; ++i) cin >> a[i];
    
        int len = 0;//记录最长连续子序列
        for(int i = 0, j = 0; i < n; ++i)
        {
            s[a[i]]++;
            while(/*j <= i&& 没必要写*/s[a[i]] > 1)//当s[a[i]]出现的次数大于1时,[j, i]区间构成的子序列就必定有重复元素
            {
                s[a[j]]--;
                j++;
            }
            len = max(len, i - j + 1);
        }
    
        cout << len << endl;
    }
    

    声明:acWing课程学习总结
    作者:DriftingAE86

  • 相关阅读:
    FTP命令行工具NCFTP
    XP 通过无线网卡 建立对等网
    Silverlight WCF 压缩
    EntityFramework Linq查询
    UCS2编码转换C#
    C#7Z压缩
    c#公钥加密私钥解密和验证
    SVN global ignore pattern for c#
    典型的DIV CSS三行二列居中高度自适应布局
    VC#窗体的大小设置
  • 原文地址:https://www.cnblogs.com/theSunAndSnow/p/12254389.html
Copyright © 2020-2023  润新知