76. 最小覆盖子串
438. 找到字符串中所有字母异位词
两个都是字符串里面使用滑动窗口,我认为有着他们的特定和共性,所以总结出来。
第一个题的窗口大小是变化的,第二个题使用的是固定大小的滑动窗口。
题解写好了注释,实在看不懂的话,拿出纸和笔推演一下就懂了。
- 最小覆盖子串:
class Solution {
public String minWindow(String s, String t) {
int[] temp = new int[123];//模拟所有的字母。
for(int i = 0; i < t.length(); ++i){//在arr中记录下t中字符出现次数。
temp[t.charAt(i)]++;
}
int left = 0, right = 0;//定义左右边界。
int count = t.length(); //用来记录s中。
int start = 0;//用来记录最小子串的开始下标
int min = Integer.MAX_VALUE;//用来记录最小子串长度。
while(right < s.length()){
char c = s.charAt(right);
if(temp[c] > 0){
count--;//发现一个t中含有的字符
}
temp[c]--;//发现过的字符,就不用重复使用了。
if(count == 0){
while(left < right && temp[s.charAt(left)] < 0){//left移到第一个等于0的字符,也就是满足条件的子串的开始下标。
temp[s.charAt(left)]++;//把之前的填好。
left++;
}
if(right - left + 1 < min){//如果出现更小的子串。
min = right - left + 1;
start = left;
}
temp[s.charAt(left)]++;//窗口左边界收缩
left++;
count++;
}
right++;//窗口有边界扩充。
}
return min == Integer.MAX_VALUE?"":s.substring(start, start+min);
}
}
- 找到字符串中所有字母异位词
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> result = new ArrayList<>();
if(p.length() > s.length()) return result;//特殊情况直接返回
int[] arr = new int[26];//模拟26位小写字母
for(char data : p.toCharArray()){//在arr中记录下p中字符出现次数
arr[data - 'a']++;
}
int left = 0, right = 0;//定义左右边界,这个窗口的大小是固定的。
int count = p.length();//记录窗口中还需要多少个p中的字符。
for(; right< p.length(); ++right){//固定滑动窗口。
if(--arr[s.charAt(right) - 'a'] >= 0) count--;//如果这个值--之后还大于等于0,说明是p中的字符。
}
if(count == 0) result.add(0);//窗口中字符满足条件了。
while(right < s.length()){//开始滑动
if(++arr[s.charAt(left++) - 'a'] > 0) count++;//左边界收缩的时候,将arr恢复,并且如果自增大于零,说明弹出了一个p中字符,count++
if(--arr[s.charAt(right++) - 'a'] >= 0) count--;//右边界扩充,如果这个值--之后还大于等于0,说明是p中的字符。
if(count == 0) result.add(left);//窗口中字符满足条件了。
}
return result;
}
}