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.
这题很有意思,是LeetCode上最有意思的题目之一。
我的解法时间复杂度是O(N)。我没想明白需要怎么描述我的解法,就不写了。
需要注意S="a",T="aa"的情况。
package leetcode;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
public class MinimumWindowSubstring {
public static void main(String[] args) {
System.out.println(new MinimumWindowSubstring().minWindow("ADOBECODEBANC", "ABC"));
}
public String minWindow(String S, String T) {
if (T.length() > S.length()) {
return "";
}
//各字符在T中出现的次数
HashMap<Character, Integer> countMap = new HashMap<Character, Integer>();
for (int i = 0; i < T.length(); i++) {
Integer count = countMap.get(T.charAt(i));
if (count == null) {
count = 0;
}
countMap.put(T.charAt(i), count+1);
}
//搜索S时,保存出现的字符和索引,KEY是字符,List保存字符在S中的索引,
//因为T中可能出现重复字符的情况,如S="aa",T="aa"。同一字符可能需要多次匹配,故将其在S中出现的坐标需要保存在List中
HashMap<Character, LinkedList<Integer>> map = new HashMap<Character, LinkedList<Integer>>();
//引入indexMap和indexQueue,以方便查找minIndex
boolean[] indexMap = new boolean[S.length()];//标记S中的字符是否出现当前待选匹配中
Arrays.fill(indexMap, false);
LinkedList<Integer> indexQueue = new LinkedList<Integer>();//保存S中出现的所有T中字符
int index = 0;
int minLen = Integer.MAX_VALUE;
int minIndex = -1;
int minStart = -1;
int windowCount = 0;
while (index < S.length()) {
char c = S.charAt(index);
Integer count = countMap.get(c);
if (count != null) {
LinkedList<Integer> indexList = map.get(c);
if (indexList == null) {
indexList = new LinkedList<Integer>();
map.put(c, indexList);
}
if (indexList.size() == count) {
indexList.add(index);
Integer firstIndex = indexList.getFirst();
indexList.removeFirst();
indexMap[firstIndex] = false;
indexMap[index] = true;
indexQueue.addLast(index);
//update minIndex
if (firstIndex == minIndex) {
Integer inx = indexQueue.getFirst();
while (!indexMap[inx]) {
indexQueue.removeFirst();
inx = indexQueue.getFirst();
}
minIndex = inx;
}
} else {
indexList.add(index);
if (minIndex == -1) {
minIndex = index;
}
windowCount++;
indexMap[index] = true;
indexQueue.addLast(index);
}
if (windowCount == T.length()) { //get an answer
int len = index - minIndex + 1;
if (len < minLen) {
minLen = len;
minStart = minIndex;
}
}
}
index++;
}
if (minStart == -1) {
return "";
}
return S.substring(minStart, minStart + minLen);
}
}