Time: O(n)
Space: O(n)
双指针/滑动窗口其实关键的都是想清楚左右边界要怎么移动。这道题动的感觉有点像队列但不太一样。
第一步要想到把t转化成map。因为t的字母在s里的顺序是没有要求的,相当于是对单个字符查验,想到这里就很容易想到要用map存(因为题目也说了可能t会有重复的字母)。
在s里匹配的时候,很容易想到最暴力的做法,就是n:s.length()为开始,然后往后找直到找全t里的所有字母。首先从n=0开始,找齐之后是窗口的初始位置。此时是没必要往后继续的,因为题目要的是最短。假如我们是最简单粗暴的暴力,那么接下来就是n=1,一直往后直到找齐。这里仔细思考一下,就能想到其实s[0]是有两种情况的,s[0]是t的字母或者不是。假如s[0]不是t的字母,那它其实删掉了也不影响剩下部分满足条件。假如s[0]是t的字母,那么此时从n=1开始,t的字母就是不全的,需要继续向后直到找全。
其实如果不是这题tag写了滑动窗口,感觉还是挺难想的。但如果一开始就知道是滑动窗口,做的时候其实关注点就是确定了窗口的初始位置之后,左右该分别如何移动。这题的切入点其实就是s[0]的两种情况,因为题目要求是找最小,所以容易想到肯定是左右没用的字母都划掉才是我们要的答案。
所以移动方式应该是:从left=0开始,right先不断后移找齐所有字母。之后,left右移一位,如果Left是t的字母,则right继续右移直到再次找齐。若left不是,则left继续移动直到它是t的字母。结束条件就是left走到了最后(或者其实应该是left < s.length()-t.length() )
特殊情况:s<t,直接返回““
涉及到java的hashmap操作和string操作比较多。
1.string的substring(index1, index2)截取的时候,是不包含index2的,所以这里要+1
2.hashmap的replace操作,最好有个中间变量。不然就会出各种奇怪的错……看了半天也没明白是啥🚬
class Solution {
public String minWindow(String s, String t) {
if(s.length()<t.length()) return "";
HashMap<Character, Integer> T = new HashMap<Character, Integer>();
HashMap<Character, Integer> WindowMap = new HashMap<Character, Integer>();
int Tcnt = 0, Wcnt = 0, ans = 100001;
String strans = new String();
// convert t to map
for(int i = 0;i<t.length();i++){
if(T.containsKey(t.charAt(i))){
int tmp = T.get(t.charAt(i));
T.replace(t.charAt(i), tmp+1);
}
else
T.put(t.charAt(i), 1);
Tcnt++;
}
// create window map
for(char iter:T.keySet()){
// System.out.println(iter);
WindowMap.put(iter, 0);
}
int left = 0, right = 0;
if(WindowMap.containsKey(s.charAt(0))){
if(WindowMap.get(s.charAt(0)) < T.get(s.charAt(0)))
Wcnt++;
WindowMap.replace(s.charAt(0), 1);
}
while(left < s.length()){
while(Wcnt < Tcnt){
right++;
if(right >= s.length())
break;
if(WindowMap.containsKey(s.charAt(right))){
int tmpk = WindowMap.get(s.charAt(right));
if(tmpk < T.get(s.charAt(right)))
Wcnt++;
WindowMap.replace(s.charAt(right), tmpk+1);
}
}
// System.out.println("left "+left+" right "+right+" Wcnt "+Wcnt+" Tcnt "+Tcnt+" ans "+strans);
int tmplen = right-left+1;
if((Wcnt == Tcnt) && (tmplen < ans)){
ans = tmplen;
strans = s.substring(left, right+1);
}
if(WindowMap.containsKey(s.charAt(left))){
int tmpx = WindowMap.get(s.charAt(left));
if(tmpx == T.get(s.charAt(left)))
Wcnt--;
WindowMap.replace(s.charAt(left), tmpx-1);
}
left++;
}
return strans;
}
}