题目:
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.
解法:
首先将T变成一个字典,用HashMap存储,key为字符,value为该字符的个数。
用start指向S中窗口的开始位置,end指向窗口的结尾位置,初始值为0,开始遍历end
当遇到T中的字符时,将该字符的计数减一,如果剩余数大于等于0,说明是一个有用的字符,如果小于0说明这个字符已经太多了。我们设置一了记录有用字符个数的计数器count,如果count等于T的长度时,就说明这是一个有效的窗口,但是这个窗口不一定是最优的,因为可能包含不需要的T中字符。、
这个时候我们就可以移动start指针,当start指向一个T中字符,判断它是否是多余的,如果不是,那么这个窗口就是一个局部最优解,如果是多余的,start就继续右移(不会超过end的)。
当找到一个局部最优解后,就可以继续移动end指针。以此类推,直到end移动到S末尾。
最后,我们只用在所有局部最优解中找到最优的即可,整个算法时间复杂度为O(2n+m)
import java.util.HashMap;
public class No76_MinimumWindowSubstring {
public static void main(String[] args){
System.out.println(minWindow("ADOBECODEBANC", "ABC"));
System.out.println(minWindow("AADBCAB", "ABC"));
System.out.println(minWindow("", ""));
}
public static String minWindow(String S, String T) {
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
for(int i=0;i<T.length();i++){
char c = T.charAt(i);
if(map.get(c) == null)
map.put(c, 1);
else
map.put(c, map.get(c)+1);
}
int start = 0;
int end = 0;
int count = 0;
int maxlen = S.length()+1;
String ret = "";
for(;end<S.length();end++){
char c = S.charAt(end);
if(map.containsKey(c)){
map.put(c, map.get(c)-1);
if(map.get(c) >= 0) count++;
while(count == T.length()){
if(map.containsKey(S.charAt(start))){
map.put(S.charAt(start), map.get(S.charAt(start))+1);
if(map.get(S.charAt(start)) > 0){
if(maxlen > end-start+1){
ret = S.substring(start, end+1);
maxlen = end-start+1;
}
count--;
}
}
start++;
}
}
}
return ret;
}
}