Sliding Window
滑动窗口算法:
滑动窗口一般用于一个数组中,使用该窗口在数组合法区间内滑动,动态记录相关信息,从而提高算法复杂度
题目1:不包含相同元素的最长子串
题目描述:给定一个字符串,找出其中不含有重复字符的 最长子串 的长度。
输入:“abcgbef”
输出:5
算法思想
数组模拟队列,front标记窗口左端,i记录窗口右端,i从0遍历到数组末端.
map<char,int>存放不同元素出现在窗口中的次数.1
map<char, int> mp;
开始front=0,i一直右移,map记录元素直至出现重复字符name,有mp[name]==2,记下字串长度res.
i再要后移,则需舍去之前出现的重复字符,于是front右移至 a[front]==name.
每次出现重复字符时就考虑更新字串长度res.
——————————————————————————————————————
·代码如下·
1 |
|
题目2:至少包含k个相同元素的最短子串
题目描述
给长度为n的一段字符,要求截取一段连续字串,满足至少包含k个相同字符,求该字串长度的最小值
输入:9 2
abebeabee
输出:2
- 算法思想
该题求至少k个字符的最短长度,即窗口内仅包含k个字符,并且
k=1时,显然最短res为1;
k>1时,最短时应满足a[front]=a[i]=name,name即重复的字符. - 直接说窗口在移动时和上题的不同之处吧.
同样i右移至 mp[name]==k ,front右移直至 mp[name]==k(即a[front]==name).
这是为了将长度尽可能缩短至 a[front]=a[i]=name.
——————————————————————————————————————————
·代码如下·
1 |
|
题目3:最多包含k个相同元素的最长子串
问题描述
链接:https://ac.nowcoder.com/acm/contest/3002/H
来源:牛客网
对于一个“01”串而言,每次操作可以把’0’字符改为’1’字符,或者把’1’字符改为’0’字符。所谓“01”串,即只含字符’0’和字符’1’的字符串。
nozomi有最多 k 次操作的机会。她想在操作之后找出一个尽可能长的连续子串,这个子串上的所有字符都相同。
这个子串的长度最大值是多少? (注:k次操作机会可以不全部用完)
输入: 6 1
101110
输出: 5
(注将’0’改为’1’可得到子串最长为5,即“111110”; 将’1’改为’0’子串最长为2,即“001110”.
两者取最长 max(5,2)=5)
问题分析
分两种情况:
1)将’0’改为’1’,得到子串字符全为’1’
2)将’1’改为’0’,得到子串字符全为’0’
最后求 max(Slide(‘1’), Slide(‘0’))1
int Slide(char a) //函数返回的是更改字符a后的最长子串长度
算法思想
如 Slide(‘1’) 最终得到子串字符全为’0’,更改’1’的次数不超过k.
这里需要转化一下思想,即更改多少次字符’1’ 就是寻找’1’出现的次数.
那么该问题即转化为 “01”串中最多包含k个’1’字符的最长子串.
该问题类似题目1,稍微一点不同在于:
更改字符次数mp(也就是包含题目1中重复字符个数mp)小于等于k,而不是小于2.
——————————————————————————————————————————
·代码如下·
1 |
|
最后小结:
滑动窗口的算法思想:
窗口滑动时,始终保证窗口内是元素是满足要求的,这样滑动结束,最终就能找到问题最优解
算法时间复杂度为 窗口最大长度O(n).
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!