三连击破---滑动窗口算法---leetcode

本文所讲的滑动窗口算法不涉及计算机网络,只是单纯的算法而已

滑动窗口,顾名思义:就是一个会滑动的窗口【doge】

不难想象,它主要是解决字符串和数组的最优化问题的。关于下面几个题目,我曾花了大量时间尝试贪心和dp,收(mei)效(xie)甚(chu)微(lai)。现场学习滑动算法,连破三题

先举个栗子,我们现在有一个字符串s和字符串t,t为"ABC" ,s为“AWGUACHBGAFCB”,现在要求s中包含"ABC"(按顺序)最短子序列的长度。

我们这样:

1、定义一个双指针left和right,开始全为0,随后派出right使用for循环遍历数组。对遇到的'A' 'B' 'C'做记录

2、当子数组含有全部的'A' 'B' 'C'后,left出发while循环缩短子字符串的长度,直到刚好含有'A' 'B' 'C'位置,记录此时的子字符串(即窗口)的长度,并每次比较选择最小的那个

3、当right遍历完整个数组之后,我们也就得到了最短的窗口长度,即为所求!

代码实现起来都不难,但当我看见这个方法的时候,我很是不信!你那个right真有那么靠谱吗?它万一给你多加或少加几个不就WA了吗?!

这就需要我们在while循环是注意判断顺序,一定是先判断和修改变量条件,然后再left++,

例如,while循环时我们必须判断A在不在子序列中然后将left++,不然你先left++之后s[left]得到的‘A’符合条件,但是‘A’前面的一个字符没有去掉,导致最终的长度比答案多了一个!

题目上不尽如此;

考试的最大困扰度 - 考试的最大困扰度 - 力扣(LeetCode) (leetcode-cn.com)icon-default.png?t=M276https://leetcode-cn.com/problems/maximize-the-confusion-of-an-exam/solution/kao-shi-de-zui-da-kun-rao-du-by-leetcode-qub5/ 三连击破---滑动窗口算法---leetcode_第1张图片

 这题你看起来要比那个ABC复杂一点,但操作起来知识多了一个临时变量而已:我们需要用这个临时变量来记录相应的变量和的长度,而且因为这题的字符'T'和'F'都能够符合要求,所以我们需要把滑动窗口封装成函数调用两次,在比较最大的窗口长度,如果您觉得有难度,可以先看看下面一题

int maxfind(string answerKey, char ch,int k)
    {
        int len = answerKey.size();
        int ans = 0;
        int ret = 0;
        int left = 0;
        int right = 0;
        for (; right < len; right++)  //从前往后遍历,虽然看起来很不靠谱,但真的很有效
        {
            if (answerKey[right] != ch)
                ret++;
            while (ret > k)
            {
                if (answerKey[left] != ch)  //k代表的修改次数有限,当非标准字符串超过k时,缩小窗口,知道ret小于k
                    ret--;
                left++;  //一定是先修改ret的大小,然后left++,将多余的字符排除干净
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }

    int maxConsecutiveAnswers(string answerKey, int k) {
        int n1 = maxfind(answerKey, 'F', k);
        int n2 = maxfind(answerKey, 'T', k);
        int ans = max(n1,n2);
        return ans;
    }

 

 

1004. 最大连续1的个数 III - 力扣(LeetCode) (leetcode-cn.com)icon-default.png?t=M276https://leetcode-cn.com/problems/max-consecutive-ones-iii/这题就是彻底的模板题了!

int longestOnes(vector& nums, int k) {
        int len = nums.size();
        int ans = 0;
        int ret = 0;
        int left = 0;
        int right = 0;
        for (; right < len; right++)
        {
            if (nums[right] != 1)
                ret++;
            while (ret > k)
            {
                if (nums[left] != 1)
                    ret--;
                left++;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }

1208. 尽可能使字符串相等 - 力扣(LeetCode) (leetcode-cn.com)icon-default.png?t=M276https://leetcode-cn.com/problems/get-equal-substrings-within-budget/相当于一个小变种

int equalSubstring(string s, string t, int maxCost) {
        int i = 0;
        int len = s.size();
        int left = 0;
        int right = 0;
        int ret = 0;
        int ans = 0;
        for (; right < len; right++)
        {
            if (s[right] != t[right])
                ret += abs(s[right] - t[right]);
            while (ret > maxCost)
            {
                if (s[left] != t[left])
                    ret -= abs(s[left] - t[left]);
                left++;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }

希望和诸君共勉

PS:解决字符串最优解的办法不只有贪心和dp,还有滑动窗口!

你可能感兴趣的:(每日一题,c++,蓝桥杯)