当前位置: 首页 > news >正文

滑动窗口算法

这是一篇关于滑动窗口的教程,涵盖固定窗口和可变窗口的基本概念、应用场景,并通过实际的 Java 示例代码帮助理解。


滑动窗口算法教程

滑动窗口(Sliding Window)是一种非常高效的算法技巧,常用于处理序列(如数组、字符串等)中的问题,特别是与子数组或子字符串相关的问题。通过维护一个窗口(通常是一个连续的元素范围),并在序列上滑动,滑动窗口技巧能够大大减少计算量,提升程序性能。

1. 滑动窗口概述

滑动窗口的核心思想是使用两个指针(通常称为左指针右指针)来表示当前窗口的范围。右指针负责扩展窗口,左指针负责收缩窗口,以满足题目要求的条件。通过左右指针的移动,窗口会在数据上滑动,从而高效地求解问题。

窗口的两种类型:
  • 固定窗口大小:窗口的大小是固定的,每次滑动时,窗口的范围不变,只是向右或向左移动。
  • 可变窗口大小:窗口的大小可以变化,通常根据某些条件来扩展或收缩窗口。

2. 固定窗口大小

固定窗口大小的滑动窗口指的是窗口的大小在整个过程中保持不变。每次滑动时,窗口只向前推进,新的元素进入窗口时,最旧的元素会被移除。

应用场景:

常用于求解固定大小的子数组或子字符串的相关问题,例如计算某个固定窗口大小的子数组的和、平均值、最大值等。

示例问题:
  • 问题:给定一个数组,求所有大小为 k 的子数组的和。
public class FixedSizeSlidingWindow {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6};int k = 3;int result = maxSum(arr, k);System.out.println("Maximum sum of any subarray of size " + k + " is: " + result);}public static int maxSum(int[] arr, int k) {// 初始化窗口的总和int windowSum = 0;int maxSum = 0;// 第一步:计算窗口初始值for (int i = 0; i < k; i++) {windowSum += arr[i];}maxSum = windowSum;// 第二步:滑动窗口for (int i = k; i < arr.length; i++) {// 滑动窗口:减去左边的元素,加上右边的元素windowSum += arr[i] - arr[i - k];maxSum = Math.max(maxSum, windowSum);}return maxSum;}
}
解释:
  • 初始时,我们计算数组前 k 个元素的和。
  • 然后,通过滑动窗口,逐步向右滑动,每次移出窗口左侧的元素,并加入新的右侧元素。
  • 在每次滑动时,更新窗口的和,并记录最大值。

3. 可变窗口大小

可变窗口大小的滑动窗口指的是窗口的大小是动态变化的,通常依据某些条件来扩展或收缩窗口。这种方法通常用于一些更复杂的情况,如寻找某种满足条件的子数组。

应用场景:

常用于解决一些求解最大、最小子数组的问题,如:

  • 寻找一个和小于某个值的最长子数组。
  • 寻找一个包含所有不同字符的最小子字符串。
示例问题:
  • 问题:给定一个字符串,找出其中没有重复字符的最长子字符串的长度。
import java.util.HashSet;public class VariableSizeSlidingWindow {public static void main(String[] args) {String input = "abcabcbb";System.out.println("Length of the longest substring without repeating characters: " + lengthOfLongestSubstring(input));}public static int lengthOfLongestSubstring(String s) {HashSet<Character> set = new HashSet<>();int left = 0; // 左指针int maxLength = 0;// 右指针从左到右滑动for (int right = 0; right < s.length(); right++) {// 如果字符已经存在于集合中,收缩窗口,移动左指针while (set.contains(s.charAt(right))) {set.remove(s.charAt(left));left++;}// 将当前字符加入集合set.add(s.charAt(right));// 更新最大长度maxLength = Math.max(maxLength, right - left + 1);}return maxLength;}
}
解释:
  • 左指针 left右指针 right 共同构成一个窗口。
  • 每次扩展 right 指针时,检查窗口内是否有重复的字符。如果有,就移动 left 指针来收缩窗口,直到窗口内没有重复字符为止。
  • right - left + 1 计算的是当前窗口内字符的个数,maxLength 用于记录遇到的最大长度。

4. 滑动窗口的时间复杂度

  • 固定窗口:每个元素最多只会被加入和移出一次,所以时间复杂度是 O(n),其中 n 是数组的长度。
  • 可变窗口:左右指针各自最多遍历一次整个数组,时间复杂度也是 O(n)。

因此,滑动窗口技术能够将一些传统的暴力算法的时间复杂度从 O(n^2) 降低到 O(n),大大提升算法效率。


5. 总结

滑动窗口是一种高效的算法技巧,适用于处理涉及子数组或子字符串的问题。通过维护一个动态或固定大小的窗口,滑动窗口能够高效地解决问题,减少不必要的计算。

  • 固定窗口:适用于子数组大小固定的问题,例如求和、求最大最小值。
  • 可变窗口:适用于更灵活的问题,例如查找满足条件的最长/最短子数组。

滑动窗口的关键是利用两个指针来表示窗口的起始和结束位置,逐步调整窗口的大小,快速求解问题。


通过这些示例和解释,希望你对滑动窗口算法有了更清晰的理解,并能够在实际编程中灵活应用它。


http://www.mrgr.cn/news/66898.html

相关文章:

  • Netty原来就是这样啊(二)
  • Redis应用(6)接口限流
  • Linux云计算 |【第五阶段】PROJECT3-DAY1
  • AttriPrompter:基于属性语义的自动提示,用于通过视觉-语言预训练模型实现零样本细胞核检测|文献速递-基于深度学习的病灶分割与数据超分辨率
  • ROS2简介与Ubuntu24.04中安装指南
  • 【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用
  • sql专题 之 常用命令
  • Java学习路线:Maven(一)认识Maven
  • 程序员开发速查表
  • Swift 开发教程系列 - 第8章:协议与扩展
  • 使用python实现关键字排名追踪——跟踪你的网站在过去12个月搜索引擎排名和关键字表现
  • 代码随想录训练营Day18 | 77. 组合 - 216.组合总和III - 17.电话号码的字母组合
  • 【Homework】【1--3】Learning resources for DQ Robotics in MATLAB
  • MyBatis 返回 Map 或 List<Map>时,时间类型数据,默认为LocalDateTime,响应给前端默认含有‘T‘字符
  • 图片怎么用二维码存储展展示?扫码预览图片的制作方法
  • 利用SCF文件构建网络渗透
  • 主流OLAP对比
  • 舜宇光学科技入职测评:北森商业推理40分钟28题真题解析、网盘资料下载、答题技巧
  • 思维导图:释放大脑潜能的图形工具
  • 【综合算法学习】(第二十篇)
  • 春季全国糖酒会为什么一直选择成都作为举办地......
  • 揭秘自闭症症状的最新研究成果和应对策略
  • 计算机网络——IP协议
  • 中电金信:企业数据赋能效果差,科学试错体系了解一下?
  • 【go从零单排】go中的nil到底是啥意思?
  • 软考高级架构 - 8.1 - 系统质量属性与架构评估 - 超详细讲解+精简总结