滑动窗口算法用双指针动态维护满足条件的子区间,时间复杂度优化至o(n);核心是right扩展、left收缩,窗口合法时更新答案;适用于求最短/最长子数组长度或满足条件的子数组个数。

Java 中实现滑动窗口算法处理数组的连续子区间问题,核心是用两个指针(left 和 right)动态维护一个“窗口”,使其满足特定条件(如和 ≤ target、无重复元素、长度固定等),避免暴力枚举所有子数组,将时间复杂度从 O(n²) 优化到 O(n)。
基础模板:双指针维护可变大小窗口
适用于求「满足某条件的最短/最长子数组长度」或「满足条件的子数组个数」。关键在于 right 扩展、left 收缩的触发逻辑:
- right 每次右移一位,把新元素加入窗口(如累加 sum、更新 map 计数)
- 只要窗口不满足条件(如 sum > target、出现重复字符),就 while 循环移动 left,剔除左端元素直至合法
- 每次窗口合法时,更新答案(如记录最小长度、累加有效个数)
示例:找和 ≤ target 的最长子数组长度
int left = 0, sum = 0, maxLen = 0;for (int right = 0; right sum += nums[right];
while (sum > target && left sum -= nums[left++];
}
maxLen = Math.max(maxLen, right - left + 1);
}
固定长度窗口:用 for 单循环更简洁
当题目明确要求窗口长度为 k(如最大/最小滑动窗口值、平均值等),无需 while 收缩,只需维护一个长度恒为 k 的区间:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先计算前 k 个元素的初始值(如和、最大值)
- 从 i = k 开始遍历,每次把 nums[i] 加入、nums[i−k] 移出,更新状态
- 可用双端队列(Deque)高效获取窗口最大/最小值(单调队列)
示例:返回每个长度为 k 的子数组的最大值(单调递减队列)
Dequeint[] res = new int[nums.length - k + 1];
for (int i = 0; i // 移除队尾较小值,维持递减
while (!dq.isEmpty() && nums[dq.peekLast()] dq.pollLast();
}
dq.offerLast(i);
// 移除超出窗口的左端下标
if (dq.peekFirst() // 窗口成型后记录结果
if (i >= k - 1) res[i - k + 1] = nums[dq.peekFirst()];
}
处理字符串/字符类问题:用数组代替 HashMap 优化
当窗口内元素范围确定(如小写字母 a–z、ASCII 0–127),用 int[128] 替代 HashMap 可避免装箱、哈希开销,显著提升性能:
- 声明 int[] count = new int[128],用 char 直接作索引:count[c]++
- 判断是否重复:if (count[c] > 1)
- 收缩时:count[nums[left++]]--
适用于「无重复字符的最长子串」「最小覆盖子串」等经典题。
常见易错点与调试建议
- 边界判断别漏:while 循环中必须写 left
- 更新答案时机要准:是在收缩后更新?还是在收缩前?取决于题目语义(如“和 ≤ target 的最长子数组”需在收缩完成后窗口才合法,此时更新)
- 窗口长度 = right − left + 1,不是 right − left
- 使用 Deque 时,offerLast/pollLast 对应队尾操作,peekFirst/pollFirst 对应队首;注意下标有效性检查
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










