zoukankan      html  css  js  c++  java
  • 双指针算法

    对于两重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

  • 相关阅读:
    【PAT甲级】1043 Is It a Binary Search Tree (25 分)(判断是否为BST的先序遍历并输出后序遍历)
    Educational Codeforces Round 73 (Rated for Div. 2)F(线段树,扫描线)
    【PAT甲级】1042 Shuffling Machine (20 分)
    【PAT甲级】1041 Be Unique (20 分)(多重集)
    【PAT甲级】1040 Longest Symmetric String (25 分)(cin.getline(s,1007))
    【PAT甲级】1039 Course List for Student (25 分)(vector嵌套于map,段错误原因未知)
    Codeforces Round #588 (Div. 2)E(DFS,思维,__gcd,树)
    2017-3-9 SQL server 数据库
    2017-3-8 学生信息展示习题
    2017-3-5 C#基础 函数--递归
  • 原文地址:https://www.cnblogs.com/theSunAndSnow/p/12254389.html
Copyright © 2011-2022 走看看