最小窗口子字符串
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
- 如果 S 中不存这样的子串,则返回空字符串
""
。 - 如果 S 中存在这样的子串,我们保证它是唯一的答案
问题已经很具体了,分析ac代码。
class Solution {
public:
string minWindow(string s, string t) {
vector<int> map(128,0);
for(auto c: t) map[c]++;
int counter = t.size(), begin = 0, end = 0, d = INT_MAX, head = 0;
while(end<s.size()){
if(map[s[end++]]-- > 0) counter--; //in t
while(counter == 0){ //valid
if(end - begin < d) d = end - (head = begin);
if(map[s[begin++]]++ == 0) counter++; //make it invalid
}
}
return d==INT_MAX? "":s.substr(head, d);
}
};
定义ascII 128 字符hash 是在字符串处理中,检测是否出现过的常用做法。
通过第一行第二行代码确定了需要包含的字符范围;我最初的想法是建立一个unorder_map 实质是一样的。
对于字符串处理这种方法更经济直观。
对于截取子串来说。 在 counter 等于零的时候 ,
end 到 begin 一定是一条包含子串,这个时候 需要判断是否是最短的子串。
长度就等 end - begin。先记录下来。 然后在改变原先的map 现在需要的是继续搜索下一串子串,头指针前移hash自加。但是问题是这样不就不知道子串是不是包含t 了么。依然是知道的。注意看if(map[s[end++]]-- > 0) counter--; //in t 这个代码。在这里map中原来为1的变成了零,但是原来没有的字符变成的是-1;在哈希中就实现了不包含的字符串就跳过了。当等于零的点在后一个循环中又出现时,说明包含的字符出现了,那么给他自加到1,而没有包含的字符从-1自加到零。counter 在自加1。跳出内层循环。同时相当于扔掉最早的出现的一个包含字符。尾部继续搜索最先出现的这个字符。
整个算法拆开来就是这样。 其中关键的有几点
主循环只走一遍,end 在循环内无脑自加,同时利用hash检测是否包含。同时又标记是否遍历过。 记录当前查找进度
内层循环 主要功能 第一记录当前找到的字符串长度,与位置。第二,丢掉最先找到的包含字符,让外循环继续寻找这个字符在尾部。