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".
题意:在字符串S中找到包含所有字符串T中字符的最短子串,如果找不到返回空字符串。T中可能存在重复字符,如aac,此时S中的最短子串中必须也要有两个a。
自己的思路是用一个整型数组作为map存T中包含的字符,遍历S,用一个队列存遍历过的字符,如果字符在map中并且值大于0,就将这个值减一,当这个map中所有值都是0的时候,就找到了一个包含T的子串。考虑后觉得每次都check一次map,效率很低,想到可以用一个count计数来判断。但是这个做法有个问题,就是无法缩短队列,更新最短长度。
最后查看discuss的解法后发现:
1、用map的思路是一样的。但是正解没有用队列来存储字符串,而是通过两个指针来表示;
2、不是只更新map中T含有的字符的值,而是对所有遍历到的S的字符,都对map做--操作。这样在更新左指针的时候,只要相应的++就可以了。
public String minWindow(String s, String t) {
if (s == null || s.length() == 0) {
return "";
}
int[] map = new int[256];
for (int i = 0; i < t.length(); i++) {
map[t.charAt(i)]++;
}
int count = t.length(), head = 0, begin = 0, end = 0, min = Integer.MAX_VALUE;
while (end < s.length()) {
if (map[s.charAt(end)] > 0) {
count--;
}
map[s.charAt(end)]--;
while (count == 0) {
if (end - begin + 1 < min) {
min = end - begin + 1;
head = begin;
}
if (map[s.charAt(begin)] == 0) {
count++;
}
map[s.charAt(begin)]++;
begin++;
}
end++;
}
return min > s.length() ? "" : s.substring(head, head + min);
}