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.
code 1
public class Solution { public String minWindow(String S, String T) { if(T.length() == 0 || S.length() < T.length()) return ""; Map<Character, Integer> mult = new HashMap<Character, Integer>(); Map<Character, Integer> alreadyRead = new HashMap<Character, Integer>(); for(int i = 0; i < T.length(); ++i){ if(mult.containsKey(T.charAt(i))) mult.put(T.charAt(i), mult.get(T.charAt(i)) + 1); else { mult.put(T.charAt(i), 1); alreadyRead.put(T.charAt(i), 0); } } String minWindow = ""; int cnt = 0, start = 0, end = 0, currentLength = S.length() + 1; for(; end < S.length(); ++end){ if(!mult.containsKey(S.charAt(end))) continue; else { int num = alreadyRead.get(S.charAt(end)); alreadyRead.put(S.charAt(end), num + 1); if(num + 1 <= mult.get(S.charAt(end))) ++cnt; } if(cnt == T.length()){ while(!mult.containsKey(S.charAt(start)) || alreadyRead.get(S.charAt(start)) > mult.get(S.charAt(start))){ if(mult.containsKey(S.charAt(start))){ int num = alreadyRead.get(S.charAt(start)); alreadyRead.put(S.charAt(start), num - 1); } ++start; } if(end - start + 1 < currentLength) { minWindow = S.substring(start, end + 1); currentLength = end - start + 1; } } } return minWindow; } }
the following two codes follow the same algorithm with different data structures. Both are accepted
public class Solution { public String minWindow(String S, String T) { String result = ""; int slen = S.length(), tlen = T.length(); if(slen > 0 && tlen > 0 && slen >= tlen){ HashMap<Character, Integer> mult = new HashMap<Character, Integer>(); for(int i = 0; i < tlen; ++i){ int mu = 1; if(mult.containsKey(T.charAt(i))) mu = mult.get(T.charAt(i)) + 1; mult.put(T.charAt(i), mu); } //find the substring of S which contains all characters in T int size = mult.size(); int start = 0, end = 0; for(int i = 0; i < slen; ++i){ if(mult.containsKey(S.charAt(i))){ int mu = mult.get(S.charAt(i)) - 1; if(mu == 0) --size; mult.put(S.charAt(i), mu); } if(size == 0) break; ++end; } if(size == 0){ start = shorten(start, end, mult, S); result = S.substring(start, end + 1); int len = end - start + 1, newend = end; while(newend + 1 < slen){ ++newend; if(mult.containsKey(S.charAt(newend))){ int mu = mult.get(S.charAt(newend)) - 1; mult.put(S.charAt(newend), mu); start = shorten(start, newend, mult, S); if(newend - start + 1 < len){ result = S.substring(start, newend + 1); len = newend - start + 1; end = newend; } } } } } return result; } public int shorten(int start, int end, HashMap<Character, Integer> mult, String S){ while(start < end){ if(!mult.containsKey(S.charAt(start))) ++start; else{ if(mult.get(S.charAt(start)) < 0){ int j = mult.get(S.charAt(start)) + 1; mult.put(S.charAt(start), j); ++start; } else break; } } return start; } }
Another code
public class Solution { public String minWindow(String S, String T) { String result = ""; int slen = S.length(), tlen = T.length(); if(slen > 0 && tlen > 0 && slen >= tlen){ int[] target = new int[256]; int distChar = 0; for(int i = 0; i < tlen; ++i){ ++target[T.charAt(i)]; distChar = (target[T.charAt(i)] == 1)? distChar + 1 : distChar; } int start = 0, end = 0; int[] source = new int[256]; for(int i = 0; i < slen; ++i){ if(target[S.charAt(i)] != 0){ ++source[S.charAt(i)]; distChar = (source[S.charAt(i)] == target[S.charAt(i)]) ? distChar - 1: distChar; } if(distChar == 0) break; ++end; } if(distChar == 0){ start = shorten(target, source, start, end, S); result = S.substring(start, end + 1); int len = end - start + 1, newend = end; while(newend + 1 < slen){ ++newend; if(target[S.charAt(newend)] != 0){ ++source[S.charAt(newend)]; start = shorten(target, source, start, newend, S); if(newend - start + 1 < len){ len = newend - start + 1; end = newend; result = S.substring(start, end + 1); } } } } } return result; } public static int shorten(int[] target, int[] source, int start, int end, String S){ while(start < end){ if(target[S.charAt(start)] == 0) ++start; else{ if(source[S.charAt(start)] > target[S.charAt(start)]){ --source[S.charAt(start)]; ++start; } else break; } } return start; } }