滑动窗口,顾名思义就是一个在数组或者字符串中连续的一个子数组,或者沿着轨道开动”列车“,而定长滑动窗口,就是长度固定的列车,在数组中可以前后移动(移除/添加)
我们以LeetCode的一道例题来看。(感谢灵茶山艾府的Leetcode题单!本系列文章只是用自己的话把算法解释给自己看(?)希望自己日后Review的时候能看懂23333。)
给你字符串
s和整数k。请返回字符串
s中长度为k的单个子字符串中可能包含的最大元音字母数。英文中的 元音字母 为(
a,e,i,o,u)。示例 1:
输入:s = "abciiidef", k = 3 输出:3 解释:子字符串 "iii" 包含 3 个元音字母。示例 2:
输入:s = "aeiou", k = 2 输出:2 解释:任意长度为 2 的子字符串都包含 2 个元音字母。示例 3:
输入:s = "leetcode", k = 3 输出:2 解释:"lee"、"eet" 和 "ode" 都包含 2 个元音字母。示例 4:
输入:s = "rhythms", k = 4 输出:0 解释:字符串 s 中不含任何元音字母。示例 5:
输入:s = "tryhard", k = 4 输出:1提示:
1 <= s.length <= 10^5s由小写英文字母组成1 <= k <= s.length
从题目中我们可以看出,长度为k的子字符串就是一个定长的滑动窗口!我们要找出这个滑动窗口内最多会同时出现几个元音字母。
我们可以先构造一个初始的滑动窗口,右端点(i)长度从1开始增长,如果添加的元素为元音则元音+1,同时用Math.max(a,b)函数去记录元音字母同时的最大值,当长度达到k时,即形成了定长窗口,列车再往前开,这个时候就要操作左端点(i-k+1),把尾巴给移除掉了,此时要判断移除的是否为元音,如果是,则元音要-1。
欸,为什么是i-k+1呢,我们来看下面几种情况:
[1,4) -> [1,2,3] -> 4-1 = 3
[1,4] -> [1,2,3,4] -> 4-1+1=4
(1,4) -> [2,3] -> 4-1-1=2
很明显,滑动窗口的意图是左右都闭合的情况,所以就是[left,i],在已知窗口长度为k的情况下,求得左端点i-k+1。
这个模板按照 入->更新->出 的顺序,所以每一次循环结束的时候,滑动窗口都是等待前方新元素加入的临界状态。
class Solution {
public int maxVowels(String s, int k) {
char[] S = s.toCharArray();
int ans = 0;
int vowel = 0;
for(int i = 0 ; i < S.length;i++){
if(ans == k){
return ans;
}
if(S[i] == 'a' || S[i] == 'e' || S[i] =='i' || S[i] == 'o' || S[i] == 'u'){
vowel++;
}
int left = i-k+1;
if(left<0){
continue;
}
ans = Math.max(ans,vowel);
char out = S[left];
if (out == 'a' || out == 'e' || out == 'i' || out == 'o' || out == 'u') {
vowel--;
}
}
return ans;
}
}
9.26练习更新:
刷 子数组最大平均数 I,和例题发现有不一样!求的是平均数最大值,但是数中有负数,所以不能直接int result=0;,而是用int result=Integer.MIN_VALUE来确保result起始的时候是边界值!