乍一看和最长公共子序列好像,仔细一想对不起我写不出状态转移过程,放弃。那么我们如何求这道题呢,再再再次看了讨论区,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区间最小。
