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.
题目大意: 在给定字符串s中,找出长度最短的且包含t中所有字符的子字符串,难点在于要在O(n)下完成
思路:需要借助两个指针表示字符串的头指针和尾指针。从原字符串开头开始,首先移动尾指针,一直到字符串包含所有字符,记录下当前子字符串长度。然后开始移动头指针,移到第一个使得子字符串无效(不再包含所有字符)时,跳出循环。重复上一步移动尾指针,直到遍历完s。
预处理很重要:这里用一个int[257]的数组来保存符合要求的字符串可能出现的字符的个数,因为ASCII字符最多256个。移动尾指针来达到满足条件的子字符串,移动头指针来获取当前最短且满足条件的子字符串
对于大部分找满足某些限制子符串的问题,一般都是通过使用hashmap和两个辅助指针来解决问题
public static String minWindow(String S, String T) {
int start = 0,end = 0,dist = Integer.MAX_VALUE,head=0;
int count = T.length();
int[] needCharCount = new int[257];
//可以使用int[257]来进行预处理,ASCII字符最多256个
char[] chS = S.toCharArray();
char[] chT = T.toCharArray();
for (char c: chT)
needCharCount[c]++;
while (end < S.length())
{
char cur = chS[end];
if (needCharCount[cur] > 0)
count--;
needCharCount[cur]--;
//每次都needCharCount[cur]--, 真正需要的字符计数最小为0,有重复会出现负数,比如窗口内有2个B,那么B的计数就会是-1,而不需要的字符计数会小于0
end++;
while (start<end && count == 0)
{
if (end - start< dist) {
head =start;
//需要head当临时变量存储,start一直在往后删,这里需要记录满足条件的最后位置的start
dist = end - start;
}
needCharCount[chS[start]]++;
//这里每次都needCharCount[start]++,这里遍历的都是之前已经遍历过的,所以每次都++,并不会使得不需要的字符大于0.一旦需要的字符计数大于0,那么count+1,变成无效窗口
if (needCharCount[chS[start]] >0) {
count++;
}
start++;
}
}
return dist==Integer.MAX_VALUE? "":S.substring(head, head+dist);
}
string minWindow(string s, string t) {
vector<int> map(128,0);
for(auto c: t) map[c]++;
int counter=t.size(), begin=0, end=0, d=INT_MAX, head=0;
while(end<s.size()){
if(map[s[end++]]-->0) counter--; //in t
while(counter==0){ //valid
if(end-begin<d) d=end-(head=begin);
if(map[s[begin++]]++==0) counter++; //make it invalid
}
}
return d==INT_MAX? "":s.substr(head, d);
}
for most substring problem, we are given a string and need to find a substring of it which satisfy some restrictions. A general way is to use a hashmap assisted with two pointers. The template is given below.
int findSubstring(string s){
vector<int> map(128,0);
int counter; // check whether the substring is valid
int begin=0, end=0; //two pointers, one point to tail and one head
int d; //the length of substring
for() { /* initialize the hash map here */ }
while(end<s.size()){
if(map[s[end++]]-- ?){ /* modify counter here */ }
while(/* counter condition */){
/* update d here if finding minimum*/
//increase begin to make it invalid/valid again
if(map[s[begin++]]++ ?){ /*modify counter here*/ }
}
/* update d here if finding maximum*/
}
return d;
}