原题网址:https://leetcode.com/problems/minimum-window-substring/
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 empty string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
方法一:通过直方图记录。
public class Solution {
private boolean cover(int[] f1, int[] f2) {
for(int i=0; i<f1.length; i++) {
if (f1[i] < f2[i]) return false;
}
return true;
}
public String minWindow(String s, String t) {
char[] sa = s.toCharArray();
char[] ta = t.toCharArray();
if (sa.length < ta.length) return "";
if (ta.length == 0) return "";
int[] tf = new int[256];
for(int i=0; i<ta.length; i++) tf[ta[i]] ++;
int[] sf = new int[256];
int from = 0;
int minFrom = 0;
int minLength = -1;
for(int i=0; i<sa.length; i++) {
sf[sa[i]] ++;
while (cover(sf, tf)) {
if (minLength == -1 || i-from+1 < minLength) {
minFrom = from;
minLength = i-from+1;
}
sf[sa[from]] --;
from ++;
}
}
if (minLength < 0) return "";
return s.substring(minFrom, minFrom + minLength);
}
}
方法二:引入计数器,避免比较直方图。
public class Solution {
/*
这道题最初的性能瓶颈在于每次检查histogram,
网上搜索了一些方法,原来可以用一个matched计数器,避免检查histogram!
http://www.cnblogs.com/TenosDoIt/p/3461301.html
*/
private boolean cover(int[] f1, int[] f2) {
for(int i=0; i<f1.length; i++) {
if (f1[i] < f2[i]) return false;
}
return true;
}
public String minWindow(String s, String t) {
char[] sa = s.toCharArray();
char[] ta = t.toCharArray();
if (sa.length < ta.length) return "";
if (ta.length == 0) return "";
int[] tf = new int[256];
for(int i=0; i<ta.length; i++) tf[ta[i]] ++;
int[] sf = new int[256];
int from = 0;
int minFrom = 0;
int minLength = -1;
int matched = 0;
for(int i=0; i<sa.length; i++) {
sf[sa[i]] ++;
if (sf[sa[i]] <= tf[sa[i]]) matched ++;
if (matched == ta.length) {
do {
if (minLength == -1 || i-from+1 < minLength) {
minFrom = from;
minLength = i-from+1;
}
sf[sa[from]] --;
from ++;
} while (sf[sa[from-1]] >= tf[sa[from-1]]);
matched --;
}
}
if (minLength < 0) return "";
return s.substring(minFrom, minFrom + minLength);
}
}
另一种实现:
public class Solution {
public String minWindow(String s, String t) {
if (t.length() == 0) return "";
char[] ta = t.toCharArray();
int[] h = new int[256];
for(char ch : ta) {
h[ch]++;
}
char[] sa = s.toCharArray();
int[] f = new int[256];
int from = 0;
int match = 0;
int minFrom = 0, minSize = -1;
for(int i = 0; i < sa.length; i++) {
if (f[sa[i]]++ < h[sa[i]]) {
match++;
}
if (match == ta.length && (minSize == -1 || i - from + 1 < minSize)) {
minFrom = from;
minSize = i - from + 1;
}
while (match == ta.length || (from <= i && f[sa[from]] > h[sa[from]])) {
if (f[sa[from]] == h[sa[from]]) match--;
f[sa[from++]]--;
}
}
if (minSize == -1) return "";
return s.substring(minFrom, minFrom + minSize);
}
}