Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC"
.
Note:
If there is no such window in S that covers all characters in T, return the emtpy string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
Hash Table Two Pointers String
Solution in Java:
public class Solution {
public String minWindow(String S, String T) {
if(S==""||T==""||S.length()<T.length()) return "";
//map is a hashmap for recording the times of characters in T appear,
//and how namy times the corresponding characters appear in the window of S
Map<Character, Integer> map = new HashMap<Character, Integer>();
//build the hashmap for characters in T
for(int m=0; m<T.length(); m++){
char cur = T.charAt(m);
if(map.containsKey(cur)){
int dup = map.get(cur);
map.put(cur, ++dup);
}
else
map.put(cur, 1);
}
//need is the total number of characters in T
int need = T.length();
//find the first window in S contains T
int minstart=0, minend = S.length()-1;
for(int n=0; n<S.length();n++){
if(need==0){ //need =0 means the current window contains T
minend = n-1;
break;
}
char cur = S.charAt(n);
if(map.containsKey(cur)){
int dup = map.get(cur);
if(dup>0){ //dup >0 means to cover all characters in T,
need--; //still needing this character cur, so after adding cur, need-1;
}
map.put(cur, --dup);
}
}
if(need>0) return "";//characters in S cannot cover characters in T
//shrink for the first minstart, minend
while(!map.containsKey(S.charAt(minstart)) || map.get(S.charAt(minstart))<0){
//if map contains S.charAt(minstart) and map.get(S.charAt(minstart)) < 0, that means
//now the window in S contains more S.charAt(minstart) than it needs (the number of this //characters appear in T), we then shrink the window
if(map.containsKey(S.charAt(minstart))){
int dup = map.get(S.charAt(minstart));
map.put(S.charAt(minstart), ++dup);
}
minstart++;
}
int curstart = minstart, curend = minend;
//on the base of curstart, curend, each time shift the window to the right by one position,
//and check if the need is 0. If it is, we find another window that can cover T, and begin to
//shrink the window
while(curend<S.length()-1){
char sChar = S.charAt(curstart);
//check if the first character that will be removed from the window is needed to cover T
if(map.containsKey(sChar)){
int dup = map.get(sChar);
if(dup>=0){ //only when dup>=0, this character is needed to cover T,
need++; //so after removing this character, we need one more character to //cover T, need++
}
map.put(sChar, dup+1); //remove sChar from the window, and modify the map
}
curstart = curstart + 1;
curend = curend + 1;
char eChar = S.charAt(curend);
//check if the last character that will be added to the window is needed to cover T
if(map.containsKey(eChar)){
int dup = map.get(eChar);
if(dup>0){ //only when dup>0, this character is needed to cover T
need--; //so after adding this character, we need one less character to cover T
//so we have need--
}
map.put(eChar, --dup);
}
if(need==0){ //begin to shrink
while(!map.containsKey(S.charAt(curstart)) || map.get(S.charAt(curstart))<0){
if(map.containsKey(S.charAt(curstart))){
int dup = map.get(S.charAt(curstart));
map.put(S.charAt(curstart), ++dup);
}
curstart++;
}
minstart = curstart;
minend = curend;
}
}
return S.substring(minstart, minend+1);
}
}
Note:
1. 注意a++和++a的区别,a++第一遍先返回a再执行++(居然被这个坑了。。)
2. 首先找出S中包含T的第一个窗口(如果存在),然后以此窗口位基础,以这个宽度不断向右平移,如果新窗口能够包含T,再试图缩小窗口,获得更小的窗口
3. hashmap map中,以相应字符为key值,而相对应的value表示该字符在现在的window中是刚好(value=0), 是缺乏(value>0),还是富余(value<0)