LeetCode: 76. Minimum Window Substring
LeetCode: 76. Minimum Window Substring
题目描述
Given a string S
and a string T
, find the minimum window in S
which will contain all the characters in T
in complexity O(n)
.
For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC"
.
Note:
If there is no such window in S that covers all characters in T
, return the empty string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S
.
题目大意:在 S
串中找到一段子串 s
(窗口), 使其含有 T
串的所有字母。要求算法复杂度为 O(n)
。
解题思路 —— 步步为营,庖丁解牛
- 找到第一个窗口。
- 根据第一个窗口,求出下一个窗口。
- 以此类推,计算出最小窗口。
AC 代码
class Solution {
private:
// find the first window, [first, second).
// the second of return value is 0, if there is no window in s.
pair<size_t, size_t> findFirstWnd(string s, string t, map<char, int>& tCharNumMap)
{
if(t.empty() && !s.empty()) return {0, 1};
pair<size_t, size_t> firstWnd{0, 0};
size_t count = t.size();
for(size_t i = 0; i < s.size() && count > 0; ++i)
{
if(tCharNumMap.find(s[i]) == tCharNumMap.end())
{
continue;
}
if(count == s.size()) firstWnd.first = i;
if(tCharNumMap[s[i]] > 0)
{
--count;
}
--tCharNumMap[s[i]];
// there are enough times of the first char aka s[i] in firstWnd.
while(tCharNumMap.find(s[firstWnd.first]) == tCharNumMap.end() || tCharNumMap[s[firstWnd.first]] < 0)
{
if(tCharNumMap.find(s[firstWnd.first]) != tCharNumMap.end()) ++tCharNumMap[s[firstWnd.first]];
++firstWnd.first;
}
if(count == 0)
{
firstWnd.second = i+1;
break;
}
}
return firstWnd;
}
// find the next window.
// the second of return value is 0, if there is no more window in s.
pair<size_t, size_t> findNextWnd(string s, string t, pair<size_t, size_t> lastWnd, map<char, int>& tCharNumMap)
{
pair<size_t, size_t> nextWnd{lastWnd.first+1, 0};
++tCharNumMap[s[lastWnd.first]];
// there is enough times of the first char aka s[i] in firstWnd.
while(tCharNumMap.find(s[nextWnd.first]) == tCharNumMap.end() || tCharNumMap[s[nextWnd.first]] < 0)
{
if(tCharNumMap.find(s[nextWnd.first]) != tCharNumMap.end()) ++tCharNumMap[s[nextWnd.first]];
++nextWnd.first;
}
for(size_t i = lastWnd.second; i < s.size(); ++i)
{
if(s[i] == s[lastWnd.first])
{
nextWnd.second = i+1;
--tCharNumMap[s[i]];
break;
}
if(tCharNumMap.find(s[i]) == tCharNumMap.end()) continue;
--tCharNumMap[s[i]];
// there are enough times of the first char aka s[i] in firstWnd.
while(tCharNumMap.find(s[nextWnd.first]) == tCharNumMap.end() || tCharNumMap[s[nextWnd.first]] < 0)
{
if(tCharNumMap.find(s[nextWnd.first]) != tCharNumMap.end()) ++tCharNumMap[s[nextWnd.first]];
++nextWnd.first;
}
}
return nextWnd;
}
public:
string minWindow(string s, string t) {
// 0. calculate the apearing time of char in string t
map<char, int> tCharNumMap;
for(char ch : t)
{
++tCharNumMap[ch];
}
// 1. find the first window
pair<size_t, size_t> firstWnd = findFirstWnd(s, t, tCharNumMap);
if(firstWnd.second == 0) return "";
// 2. keep iterating the chars in string s, and find the minmum windows.
pair<size_t, size_t> lastWnd = firstWnd;
pair<size_t, size_t> minWnd = firstWnd;
while(lastWnd.second != 0)
{
pair<size_t, size_t> nextWnd = findNextWnd(s, t, lastWnd, tCharNumMap);
if(nextWnd.second != 0 && (int)nextWnd.second - (int)nextWnd.first < (int)minWnd.second - (int)minWnd.first)
{
minWnd = nextWnd;
}
lastWnd = nextWnd;
}
return s.substr(minWnd.first, minWnd.second-minWnd.first);
}
};