滑动窗口法模板

来源:互联网 发布:win7无网络装网卡驱动 编辑:程序博客网 时间:2024/06/11 23:35

滑动窗口法用于求满足某种条件的最短或最长子数组(子串)如:

1)最小摘要

2)sum大于target的最短子数组

3)最长的无重复字符的子串

4)最长的最多有k个不同字符的子串

首先,子段问题基本框架是O(n^2)枚举加 O(n)的check判断。可以用滑动窗口法的问题的特点是,枚举时候内层循环可以不回退,因为那些解肯定没有当前找到的最优解更优。这里面也有个可行解的单调性分布问题,对于固定一个右端,可行解是单调分布的,就是找第一个失败的build问题,可行解的分布是000011111,或者11110000,前者就是最大子数组问题,后者是最小子数组问题。左边端点i的移动其实都可以二分,只不过右端枚举已经O(n)了,只是把O(n + n)变成O(n + logn),意义不大。


最短子串模板:1)外层循环遍历终点j ,2)内循环:如果当前窗口满足条件,和最最优比并保存,然后起点 i++

for (int j = 0; j < s.size(); j++) {窗口右端扩展,加进s[j], 更新条件while(满足条件) {和当前最优比较并保存窗口左端移除s[i],更新条件,i++}}

最长子串模板:当前窗口满足条件,1)外循环加进一个元素,2)内循环:如果破坏了invariant,窗口左指针不断推进以满足条件,3)内循环退出:满足条件,和最优比较并记录。

for (int j = 0; j < s.size(); j++) {窗口右端扩展,加进s[j], 更新条件while(不满足条件) {窗口左端移除s[i],更新条件,然后i++}此时重新满足条件,和最优比较并记录}

区别主要是:最短子串模板因为求最短,所以在窗口缩小的时候记录,最长子串模板是在窗口扩展时候记录


1 最短摘要:求s种包含t中所有字符的最短子串

string minWindow(string s, string t) {vector<int> table(256, 0), count(256, 0);for (char c : t) table[c]++;int i = 0, num = 0, minLen = s.size() + 1, minStart = -1;for (int j = 0; j < s.size(); j++) {if (table[s[j]] == 0) continue;if (count[s[j]] < table[s[j]]) num++;count[s[j]]++;for (; num == t.size(); i++) {if (j - i + 1 < minLen) {minLen = j - i + 1;minStart = i;}count[s[i]]--;if (table[s[i]] > 0 && count[s[i]] < table[s[i]]) num--;}}return minStart >= 0 ? s.substr(minStart, minLen) : "";}

2 和大于给定值的最小子数组,(均为正数)

def minSubArrayLen(self, s, nums):i, sum, minLen = 0, 0, len(nums) + 1for j in xrange(len(nums)):sum += nums[j]while sum >= s:minLen = min(minLen, j - i + 1)sum -= nums[i]i += 1if minLen > len(nums): return 0else: return minLen

3最长无重复字符子串:

 int lengthOfLongestSubstring(string s) {vector<int> charSet(256, -1);int maxLen = 0;for (int start = 0, i = 0; i < s.size(); i++) {if (charSet[s[i]] >= start) start = charSet[s[i]] + 1;charSet[s[i]] = i;maxLen = max(maxLen, i - start + 1);}return maxLen;}

4最长的只有k个不同字符的子串:

int lengthOfLongestSubstringKDistinct(string s, int k) {vector<int> lastPosition(256, -1);int numChars= 0, maxLen = 0;for (int start = 0, i = 0; i < s.size(); i++) {if (lastPosition[s[i]] < start) numChars++;lastPosition[s[i]] = i;while (numChars > k) {if (lastPosition[s[start]] == start) numChars--;start++;}maxLen = max(maxLen, i - start + 1);}return maxLen;}


0 0
原创粉丝点击