12-滑动窗口
一,定义
滑动窗口算法是一种用于处理数组或字符串问题的技巧,特别适合解决涉及子数组或子串的问题。它的核心思想是通过维护一个“窗口”来高效地计算或查找满足条件的子数组或子串。
基本概念
-
窗口:窗口是数组或字符串中的一个连续子区间,通常由两个指针(左指针和右指针)表示。
-
滑动:窗口的大小可以固定或动态变化,通过移动左右指针来调整窗口的位置和大小。
算法步骤
-
初始化:设置左右指针,通常都从起点开始。
-
移动右指针:扩大窗口,直到满足某个条件。
-
移动左指针:缩小窗口,直到不满足条件,同时记录或更新结果。
-
重复:继续移动右指针,重复上述过程,直到遍历完整个数组或字符串。
示例
假设我们要在一个数组中找到和大于等于某个值的最短子数组。
-
初始化:左右指针都指向数组起点,当前和为0。
-
移动右指针:逐步将右指针向右移动,累加元素,直到和大于等于目标值。
-
移动左指针:逐步将左指针向右移动,减少和,直到和小于目标值,同时记录最短子数组的长度。
-
重复:继续移动右指针,重复上述过程,直到遍历完数组。
优点
-
高效:通过滑动窗口,避免了重复计算,时间复杂度通常为O(n)。
-
灵活:适用于多种问题,如最大子数组、最小覆盖子串等。
应用场景
-
最大子数组和:找到和最大的连续子数组。
-
最小覆盖子串:找到包含所有指定字符的最短子串。
-
无重复字符的最长子串:找到不包含重复字符的最长子串。
通过滑动窗口算法,可以高效地解决许多涉及子数组或子串的问题。
二,举例
子数组最大平均数:给一个整数数组,找出平均数最大且长度为k的下标连续的子数组,并输出该最大平均数。输入:[1,12,-5,-6,50,3],k=4,输出:12.75,最大平均数(12-5-6+50)/4=12.75.
public class demo01 {
public static void main(String[] args) {
System.out.println(findMaxAverage(new int[]{1,12,-5,-6,50,3},4));
}
public static double findMaxAverage (int[] nums ,int k) {
int sum=0;
int n=nums.length;
//先统计第一个窗口的和
for(int i=0;i<k;i++) {
sum=sum+nums[i];
}
int max=sum;
for(int i=k;i<n;i++) {
sum=sum-nums[i-k]+nums[i];
max=Math.max(max,sum);//选最大值
}
return 1.0*max/k;
}
}