滑动窗口方法一般是用在要求最值,或者子序列
力扣的一道算法题,我觉得可以很好的理解滑动窗口
字符串的排列:给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。换句话说,s1 的排列之一是 s2 的 子串 。
先分析一哈,为啥要用滑动窗口,这道题要求一个字符串是否包含另一个的排列,而对于排列来说,并不会改变字符串里各个字母的数量,比如:字符串ab,他的另一个排列是ba,但是不管怎么排列,字母a的数量是1,字母b的数量是1。所以对于本题来说,就创建两个int数组来记录每个字符的数量,随后,我们创建一个s1大小的窗口,滑动窗口每向右滑动一次,就多统计一次进入窗口的字符,少统计一次离开窗口的字符。
补充一点:当判断两数组是否相等时,当对数组名称使用 ==
运算符时,运算符会比较数组的开始内存地址,而不是数组的内容。这个代码中的两个数组显然会有不同的内存地址,所以当数组相等时,也会返回false,所以我们就用Arrays的equals()方法
我们了解一下代码:
class Solution {
public boolean checkInclusion(String s1, String s2) {
int n1=s1.length(),n2=s2.length();
if(n1>n2){
return false;
}
int[] cnt1=new int[26];
int[] cnt2=new int[26];
for(int i=0;i<n1;i++){
cnt1[s1.charAt(i)-'a']++;
cnt2[s2.charAt(i)-'a']++;
}
if(Arrays.equals(cnt1,cnt2)){
return true;
}
//这里就是开始所谓的窗口滑动
for(int i=n1;i<n2;i++){
cnt2[s2.charAt(i)-'a']++;
cnt2[s2.charAt(i-n1)-'a']--;
if((Arrays.equals(cnt1,cnt2))){
return true;
}
}
return false;
}
}
在了解了前一道题以后再来一题感受一下:
无重复字符的最长字串 :给定一个字符串 s,请你找出其中不含有重复字符的 最长子串 的长度。
分析:题目要求说不含有重复字符的最长字串,说到字串是不是感觉很眼熟,是的,这道题也属于滑动窗口的范围,但是这道题不同之处在于,这道题用right作为一个指针,不断地向右滑动将获得的字符串加入到ch中,当遇到重复的字符串时,就将现在的right+1减去i,以为是将right初始值设为-1,减去已经去除的前面的字符个数i,将这时的值与answer取一个最大值。
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> ch = new HashSet<>();
int answer=0;
int right=-1;
int n=s.length();
for(int i=0;i<n;i++){
if(i!=0){
ch.remove(s.charAt(i-1));
}
while(right+1<n && !ch.contains(s.charAt(right+1))){
ch.add(s.charAt(right+1));
right++;
}
answer=Math.max(answer,right+1-i);
}
return answer;
}
}
那就这么多,欧了!