题目:76. 最小覆盖子串 - 力扣(LeetCode)
代码思路:
(滑动窗口) O(n)
这道题要求我们返回字符串 s中包含字符串 t 的全部字符的最小窗口,我们利用滑动窗口的思想解决这个问题。因此我们需要两个哈希表,hs哈希表维护的是s字符串中滑动窗口中各个字符出现多少次,ht哈希表维护的是t字符串各个字符出现多少次。如果hs哈希表中包含ht哈希表中的所有字符,并且对应的个数都不小于ht哈希表中各个字符的个数,那么说明当前的窗口是可行的,可行中的长度最短的滑动窗口就是答案。
代码:
class Solution {
public:string minWindow(string s, string t) {unordered_map<char, int> hs, ht;//把t字符串加入ht哈希表中,来保存字符串要求for (auto c : t) ht[c] ++;//在C++中,for (auto c : t) ht[c] ++; 这行代码是一个基于范围的for循环(range-based for loop),它遍历容器t中的每个元素,并对哈希表(或称为映射、字典等,这里用ht表示)中对应键的值进行递增操作。string res = "";int cnt = 0;//从现在开始,右指针i开始向右寻找,每找到一个字母就加入hs哈希表中,如果发现这个数字不是多余的字母,//对于ht来说他是有效添加,就代表这个字母还没封顶,那就cnt++//(记住,不在ht里面字母不需要cnt++,如果hs[s[i]] ++后,字母s[i]比ht里的要多,那也不用cnt++)for (int i = 0, j = 0; i < s.size(); i++) {hs[s[i]] ++;if (hs[s[i]] <= ht[s[i]]) cnt++; //不在t里面字母不需要cnt++while (hs[s[j]] > ht[s[j]]) hs[s[j++]] --;//每次i++一次,就开始看看j可不可以贪心往右移动,直到j如果再往右滑动就会使cnt减少为止,来求最短的字符串//j作为左窗口 if (cnt == t.size()) {//在左指针j往右滑动缩小窗口后,如果cnt==t.size(),恭喜你现在窗口内的字符串达到要求也就是包含s,你现在可以和res比划比划谁最短if (res.empty() || i - j + 1 < res.size())res = s.substr(j, i - j + 1);}}return res;//如果不满足条件也会直接输出res }
};
ps:
在C++中,s.substr(j, i - j + 1); 这行代码是用来从一个字符串 s 中提取一个子字符串的j 是子串开始的位置(基于0的索引)。
i - j + 1 是子串的长度。