76. Minimum Window Substring
乍一看和最长公共子序列好像,仔细一想对不起我写不出状态转移过程,放弃。那么我们如何求这道题呢,再再再次看了讨论区,OK。利用hash_map完美解决这道题,并且时间复杂度还可以。
class Solution {
public:
string minWindow(string s, string t) {
int m = s.size();
int n = t.size();
unordered_map<char, int> mp;
for (int i = 0; i < n; i++)
mp[t[i]]++;
int begin = 0, end = 0, minSize = INT_MAX;
int head = 0, tail = 0, count = n;
while (end < m)
{
if (mp[s[end]] > 0)
count--;
mp[s[end]]--;
end++;
while (count == 0)
{
if (end - begin < minSize)
{
head = begin;
tail = end;
minSize = end - begin;
}
mp[s[begin]]++;
if (mp[s[begin]] > 0)
{
count++;
}
begin++;
}
}
if (minSize == INT_MAX)
return "";
return s.substr(head, minSize);
}
};
首先我们通过将所有的t字符串中的所有字符记录到hash_map中,接着我们开始使用两个位置索引,分别是begin和end索引,end索引从begin开始依次遍历s字符串中所有字符,并且每次都会在对应的mp中执行mp[s[end]]- - 操作,同时维护一个count计数器。这样mp中会存在这几种数据,一种是t字符串中没有的字符但是经过减一操作会变成负数,而有t字符串中的字符可能依然是正数(取决于end有没有遍历到)或者经过减一操作变成0,我这里没有说重复的数字,情况是一样的,因为我维护着一个计数器。当计数器count == 0时候,说明在begin到end之间的字符已经完全包包含t字符串。这时候我们记录start和end的位置信息。同时begin索引还是移动,首先增加对应mp[s[begin]]++;但是需要判断下加一操作之后mp[s[begin]] > 0是否成立,也就是说mp[s[begin]] 之前是一个负数还是一个0,这说明了begin在s中对应的位置是否属于t中字符,如果是,则count需要+1.反之不需要,也就是压缩begin的位置,使得begin到end区间最小。