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;
}
}