题目描述
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
示例:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”
说明:
如果 S 中不存这样的子串,则返回空字符串 “”。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
思路
字符串处理一般思想就是滑动窗口,即双指针来更新窗口大小。
在滑动窗口类型的问题中都会有两个指针。一个用于延伸现有窗口的 rightright指针,和一个用于收缩窗口的leftleft 指针。在任意时刻,只有一个指针运动,而另一个保持静止。
涉及字符串和滑窗的问题需要map存储字符和对应的出现次数
unordered_map 就是哈希表(字典),它的一个方法 count(key) 相当于 containsKey(key) 可以判断键 key 是否存在。
可以使用方括号访问键对应的值 map[key]。需要注意的是,如果该 key 不存在,C++ 会自动创建这个 key,并把 map[key] 赋值为 0。
本题思路:
算法
- 初始,left指针和right指针都指向S的第一个元素.
- 将 right 指针右移,扩张窗口,直到得到一个可行窗口,亦即包含T的全部字母的窗口。
- 得到可行的窗口后,将left 指针逐个右移,若得到的窗口依然可行,则更新最小窗口大小。
- 若窗口不再可行,则跳转至 2
在第三步我们进行结果比较,如果当前可行窗口小于最小窗口,更新最小窗口。
另附讲的比较清楚的题解:
滑动窗口算法通用思想
代码
class Solution {
public:
string minWindow(string s, string t) {
int start = 0,minLen = INT_MAX;
int left = 0,right = 0;
unordered_map<char,int> needs; //存储目标字符串中的值
unordered_map<char,int> windows; //滑动窗口
for(char c : t)needs[c]++;
int match= 0;
while(right < s.size()){
char cl = s[right];
if(needs.count(cl)){
windows[cl]++;
if(windows[cl] == needs[cl])match++; //如果cl 达到出现次数,已匹配字符++
}
right ++;
while(match == needs.size()){ //windows是可行的,收缩
if(right - left < minLen){
minLen = right - left;
start = left;
}
char c2 = s[left];
if(needs.count(c2)){
windows[c2]--;
if(windows[c2] < needs[c2]) match--;
}
left++;
}
}
return minLen == INT_MAX ? "" : s.substr(start,minLen);
}
};
Leetcode(3)字符串处理思想_滑动窗口中使用数组替代map。