本文所讲的滑动窗口算法不涉及计算机网络,只是单纯的算法而已
滑动窗口,顾名思义:就是一个会滑动的窗口【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)https://leetcode-cn.com/problems/maximize-the-confusion-of-an-exam/solution/kao-shi-de-zui-da-kun-rao-du-by-leetcode-qub5/
这题你看起来要比那个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)https://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)https://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,还有滑动窗口!