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.
这题也是看了题目提示才有的思路,题目的提示是:hashtable, two pointer.
我们可以用哈希表来保存模式串中各个字符出现的次数;
然后用双指针法遍历主串:
1)开始时low和high都指向主串第一个字符(此时[low,high)子串为空);
2)high向后移动,直到[low,high)包含模式串所需要的所有字符。
3)low向后移动,直到[low,high)不能完全包含模式串所需要的所有字符,转到2)
high指向主串最后一个字符的后面,且[low,high)不能完全包含模式串所需要的所有字符时停止算法。
这里我们使用count变量来标识[low,high)是否能够完全包含模式串所需要的所有字符,count最开始标识模式串中字符的个数,,high向后移动时,若包含一个模式串的字符,count减1,同时修改哈希表;low向后移动时,若比原来少包含一个模式串的字符,count加1,同时修改哈希表。 这样我们就可以通过count是否等于0 来判断[low,high)是否能够完全包含模式串所需要的所有字符。
以下是JAVA实现,用到了HashMap,最后leetcode跑出来的性能只比42.5%的提交要好,我觉得可能是别人使用了数组来表示哈希表,有时间再实现下数组的版本。
public class Solution {
public String minWindow(String s, String t) {
int count = 0 ;
HashMap<Character,Integer> hash = new HashMap<Character, Integer>();
for(int i = 0 ; i < t.length() ; i ++){
if(hash.containsKey(t.charAt(i)))
hash.put(t.charAt(i), hash.get(t.charAt(i)) +1);
else
hash.put(t.charAt(i), 1);
count ++;
}
int start = 0,end = 0,min = s.length() +1; //存储结果;
int low = 0,high = 0; //指针
while(!(high == s.length() && count > 0 )){ //high走到底(因为左闭右开,所以high可以取到length),但是count仍大于0时停止
if(count > 0 ){
high ++;
if(hash.containsKey(s.charAt(high-1))){
if(hash.get(s.charAt(high -1)) > 0)
count --;
hash.put(s.charAt(high -1), hash.get(s.charAt(high -1)) -1);
}
}
else{
if(high - low < min){
min = high - low;
start = low;
end = high;
}
low ++ ;
if(hash.containsKey(s.charAt(low-1))){
hash.put(s.charAt(low -1), hash.get(s.charAt(low -1)) +1);
if(hash.get(s.charAt(low -1)) > 0)
count ++;
}
}
}
return s.substring(start,end);
}
}下午实现了一下数组版本的,该版本超过了93%的java提交,具体如下:声明两个数组,分别表示某字符在模式串中是否存在以及数量;这里使用两个数组是因为后面再遍历主串的时候需要修改保存数量的数组,数组中的值会出现为负的情况,所以不能单纯地以是否是负数来区别该字符在模式串中是否出现过。
public class Solution {
public String minWindow(String s, String t) {
int count = 0 ;
int[] contain = new int[256];
int[] nums = new int[256];
for(int i = 0 ; i < t.length() ; i ++){
if(contain[t.charAt(i)] == 0)
contain[t.charAt(i)] = 1;
nums[t.charAt(i)] ++ ;
count ++;
}
int start = 0,end = 0,min = s.length() +1; //存储结果;
int low = 0,high = 0; //指针
while(!(high == s.length() && count > 0 )){ //high走到底(因为左闭右开,所以high可以取到length),但是count仍大于0时停止
if(count > 0 ){
high ++;
if(contain[s.charAt(high-1)] > 0){
if(nums[s.charAt(high -1)] > 0)
count --;
nums[s.charAt(high -1)] --;
}
}
else{
if(high - low < min){
min = high - low;
start = low;
end = high;
}
low ++ ;
if(contain[s.charAt(low-1)] > 0){
nums[s.charAt(low-1)] ++;
if(nums[s.charAt(low-1)] > 0)
count ++;
}
}
}
return s.substring(start,end);
}
}
本文详细阐述了如何利用哈希表和双指针技术解决最小覆盖子串问题,包括算法步骤、代码实现以及性能优化。通过实例分析,展示了如何在复杂度为O(n)的情况下高效求解。此外,提供了数组版本的实现,性能表现优于常规版本。
1734

被折叠的 条评论
为什么被折叠?



