LeetCode/solutions/76. Minimum Window Substring.md
2020-02-28 23:46:12 +08:00

44 lines
2.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [76. Minimum Window Substring](https://leetcode.com/problems/minimum-window-substring/)
# 思路
给定字符串S和T要在S中找到一个最短的子串使得其包含了T中的所有的字母并且限制时间复杂度为 O(n)。
由于限制时间复杂度为O(n),所以我最开始想到的思路是双指针法,用两个指针 l 和 r 从S的两端分别向中间缩小但是发现这样得出的子串不一定就是最小的。
看了答案发现也是用双指针,不过不是从两端往中间缩小,而是都从最左边开始,先将 r 不断右移以扩大窗口直到包含了T的所有字符然后在包含T中所有字符的前提下尝试将 l 不断右移缩小窗口。这样一伸一缩后就是求得了当前最小的一个子串,然后再用同样的思路将两个指针向右滑动,用一个全局变量记录整个过程的最短长度。
我们可以用一个长度为128ASCII码为0-127的整型数组 cnt 来记录T串每个字符的出现次数然后还需要用一个变量 win_cnt 来记录在窗口中的包含在T中的字符数这样如果 `win_cnt == T.size()`就说明找到了满足条件的子串,更新全局变量的最短长度和起始位置。
需要特别注意 win_cnt 的更新方式当某个字符c进入窗口时只有当`--cnt[c] >= 0`时才使 cnt 加1同理当某个字符 c 离开窗口时,只有当`++cnt[c] > 0`时才使 cnt 减 1。
时间复杂度O(m+n)
# C++
``` C++
class Solution {
public:
string minWindow(string s, string t) {
int sn = s.size(), tn = t.size();
vector<int>cnt(128, 0);
for(int i = 0; i < tn; i++) cnt[t[i]]++;
int win_cnt = 0;
int l = 0, smallest_l = -1, smallest = INT_MAX;
for(int r = 0; r < sn; r++){
if(--cnt[s[r]] >= 0) win_cnt++;
while(win_cnt == tn){
if(smallest > r - l + 1){
smallest = r - l + 1;
smallest_l = l;
}
if(++cnt[s[l]] > 0) win_cnt--;
l++;
}
}
return smallest_l == -1 ? "" : s.substr(smallest_l, smallest);
}
};
```