LeetCode从低效到高效,点击
一、题目描述:
题目要求
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)链接
示例
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
二、思路分析:
本题是一道经典的双指针题目,本题中要求s中覆盖t所有字符,也就是如果t有两个'a',s的字串只要有a就可以,双指针都从0出发,i指向字串范围的最左边,j指向下一个要获取的位置,左闭右开的区间. j要尽可能向右扫描,每次发现是关键的字符则需要增加对应的windows[s[j]]的值,判断是不是匹配了,如果匹配了就开始尽量增大i的值尝试减少字串长度,直到不能匹配为止,这个时候需要j继续向右扫描.
三、AC 代码:
string minWindow(string s, string t) {
unordered_map<char,int> window;
for(auto c:t){
window[c]=0;
}
int match=window.size(),matched=0;
int i=0,j=0,minlen=0x7FFFFFFF,pos=0;
while(i<=j&&j<s.size()){
// 前面的都是加入了也不会产生作用的t里面没有的字母
while(window.find(s[j])==window.end()&&j<s.size()){
j++;
}
// 下面的j指的最后一个刚加入的位置
// 这个加入是t里面需要的,j永远指向下一个要进行匹配的值
window[s[j]]++;
// 如果加入了正好能满足一个字母的需求,匹配个数++
if(window[s[j]]==1) {
matched++;
}
// 指向下一个
j++;
// 如果满足匹配,就要考虑如何减少长度
while(matched==match){
// 先存一下
if(minlen>j-i){
minlen=j-i;
pos=i;
}
// 如果i位置是需要的字符,则需要进一步判断
if(window.find(s[i])!=window.end()){
if(window[s[i]]==1){
matched--;
}
window[s[i]]=max(--window[s[i]],0);
}
i++;
}
}
return s.substr(pos,minlen);
}
四、总结:
双指针算法并不都是从左右开始向中心扫描,也可以从一端开始扫描,双指针是对数组左右区间的扫描定位.
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情