滑动窗口 详解

news2024/11/20 10:07:58

滑动窗口详解

滑动窗口是一种高效的数组或字符串问题解决策略,通常用于解决子数组、子字符串相关的问题,如 最小窗口、最大窗口、满足条件的子数组或子字符串等


滑动窗口思想

滑动窗口的核心思想是将一段区间作为“窗口”,通过动态调整窗口的边界来满足问题的约束条件,避免不必要的重复计算,从而提高效率。

基本步骤
  1. 定义窗口的起点和终点:通常是两个指针,leftright,分别表示窗口的起始位置和结束位置。
  2. 调整窗口
    • 扩展窗口:通过增加 right 指针来扩大窗口。
    • 收缩窗口:当窗口满足某些条件时,移动 left 指针收缩窗口。
  3. 更新结果:在窗口调整的过程中,更新满足条件的结果(如最大长度、最小长度等)。

滑动窗口的适用场景

滑动窗口常用于以下问题类型:

  1. 固定窗口大小:如求固定大小子数组的最大和、最小和等。
  2. 动态窗口大小:如最长连续子数组、最短子数组、满足条件的子字符串等。

滑动窗口模板

以下是滑动窗口的一般模板:

public int slidingWindowExample(int[] nums) {
    int left = 0, right = 0; // 定义窗口的左右边界
    int result = 0;          // 存储结果
    int windowSum = 0;       // 窗口中的状态(如和、计数等)

    while (right < nums.length) {
        // 1. 增大窗口
        windowSum += nums[right];
        right++;

        // 2. 缩小窗口(当条件不满足时)
        while (windowSum > target) {
            windowSum -= nums[left];
            left++;
        }

        // 3. 更新结果
        result = Math.max(result, right - left);
    }

    return result;
}

滑动窗口应用实例

1. 固定大小的滑动窗口

问题:给定一个数组,求长度为 k 的连续子数组的最大和。

示例

输入: nums = [1, 2, 3, 4, 5, 6], k = 3
输出: 15
解释: 长度为 3 的子数组最大和为 [4, 5, 6],和为 15

代码实现

public int maxSumSubarray(int[] nums, int k) {
    int maxSum = 0, windowSum = 0;

    // 初始化第一个窗口
    for (int i = 0; i < k; i++) {
        windowSum += nums[i];
    }
    maxSum = windowSum;

    // 滑动窗口
    for (int i = k; i < nums.length; i++) {
        windowSum += nums[i] - nums[i - k];
        maxSum = Math.max(maxSum, windowSum);
    }

    return maxSum;
}

时间复杂度 O ( n ) O(n) O(n),只遍历数组一次。


2. 动态窗口大小

问题:给定一个正整数数组 nums 和一个目标值 target,找出和大于或等于 target 的最短连续子数组长度。

示例

输入: nums = [2, 3, 1, 2, 4, 3], target = 7
输出: 2
解释: 子数组 [4, 3] 的长度最短。

代码实现

public int minSubArrayLen(int target, int[] nums) {
    int left = 0, sum = 0;
    int minLength = Integer.MAX_VALUE;

    for (int right = 0; right < nums.length; right++) {
        sum += nums[right];

        // 收缩窗口,直到条件不再满足
        while (sum >= target) {
            minLength = Math.min(minLength, right - left + 1);
            sum -= nums[left];
            left++;
        }
    }

    return minLength == Integer.MAX_VALUE ? 0 : minLength;
}

时间复杂度 O ( n ) O(n) O(n),只遍历数组一次。


3. 无重复字符的最长子字符串

问题:给定一个字符串 s,找出其中无重复字符的最长子字符串的长度。

示例

输入: s = "abcabcbb"
输出: 3
解释: 无重复字符的最长子字符串是 "abc",长度为 3

代码实现

public int lengthOfLongestSubstring(String s) {
    Set<Character> window = new HashSet<>();
    int left = 0, maxLength = 0;

    for (int right = 0; right < s.length(); right++) {
        char c = s.charAt(right);

        // 如果窗口中已有字符,收缩窗口
        while (window.contains(c)) {
            window.remove(s.charAt(left));
            left++;
        }

        // 添加当前字符
        window.add(c);
        maxLength = Math.max(maxLength, right - left + 1);
    }

    return maxLength;
}

时间复杂度 O ( n ) O(n) O(n),每个字符最多进出窗口一次。


4. 最小覆盖子串

问题:给定两个字符串 st,找到 s 中最小的子串,使得该子串包含 t 中所有字符。

示例

输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"

代码实现

public String minWindow(String s, String t) {
    Map<Character, Integer> need = new HashMap<>();
    Map<Character, Integer> window = new HashMap<>();

    for (char c : t.toCharArray()) {
        need.put(c, need.getOrDefault(c, 0) + 1);
    }

    int left = 0, right = 0;
    int valid = 0, start = 0, minLength = Integer.MAX_VALUE;

    while (right < s.length()) {
        char c = s.charAt(right);
        right++;

        // 更新窗口数据
        if (need.containsKey(c)) {
            window.put(c, window.getOrDefault(c, 0) + 1);
            if (window.get(c).equals(need.get(c))) {
                valid++;
            }
        }

        // 收缩窗口
        while (valid == need.size()) {
            if (right - left < minLength) {
                start = left;
                minLength = right - left;
            }

            char d = s.charAt(left);
            left++;
            if (need.containsKey(d)) {
                if (window.get(d).equals(need.get(d))) {
                    valid--;
                }
                window.put(d, window.get(d) - 1);
            }
        }
    }

    return minLength == Integer.MAX_VALUE ? "" : s.substring(start, start + minLength);
}

时间复杂度 O ( n ) O(n) O(n),窗口左右指针均最多遍历字符串一次。


滑动窗口总结

  1. 适用场景

    • 子数组或子字符串问题,涉及窗口条件的动态变化。
    • 找到满足某些条件的最大或最小窗口。
  2. 核心思想

    • 通过动态调整窗口(扩大和收缩)满足条件,避免暴力法的多次重复遍历。
  3. 模板
    滑动窗口问题通常需要两层循环:

    • 外层:扩展窗口。
    • 内层:在条件满足时收缩窗口并更新结果。
  4. 时间复杂度

    • 大多数滑动窗口算法的时间复杂度为 O ( n ) O(n) O(n),因为窗口中的元素每次只被处理一次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2243976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt桌面应用开发 第五天(常用控件)

目录 1.QPushButton和ToolButton 1.1QPushButton 1.2ToolButton 2.RadioButton和CheckBox 2.1RadioButton单选按钮 2.2CheckBox多选按钮 3.ListWidget 4.TreeWidget控件 5.TableWidget控件 6.Containers控件 6.1QScrollArea 6.2QToolBox 6.3QTabWidget 6.4QStacke…

Vue.js 插槽 Slots 实际应用 最近重构项目的时候遇到的...

前端开发中 插槽 Slots 是一个重要的概念 我们可以查看一下vue.js的官方文档 https://cn.vuejs.org/guide/components/slots 类似于连接通道一样 可以把核心代码逻辑搬到另外的地方 做一个引用 而原先的地方可能并不能这样书写 对于这个概念我在vue的官方文档里面找到了…

ubuntu pytorch容器内安装gpu版本的ffmpeg

一、基础镜像和生成容器 pytorch/pytorch &#xff1a;1.13.1-cuda11.6-cudnn8-devel 生成容器&#xff0c;一定要加NVIDIA_DRIVER_CAPABILITIEScompute,utility,video,graphics&#xff0c;否则侯建无法推流&#xff0c;报错缺少编码之类的。 docker run -it --gpus all -e …

VSCode+ESP-IDF开发ESP32-S3-DevKitC-1(2)第一个工程 LED心跳灯

VSCodeESP-IDF开发ESP32-S3-DevKitC-1&#xff08;2&#xff09;第一个工程 LED心跳灯 前言1.新建工程2.编写控制LED代码3.LED控制独立成.c和.h文件 前言 实际开发中很多时候我们需要有一个类似心跳灯或运行指示灯的灯以不同的状态闪烁以表示程序的运行状态&#xff0c;所以第…

在ubunto18.04安装node 14.16.0

这里演示安装node 14.16.0&#xff0c;其他版本也一样的安装步骤&#xff0c;需要注意1 1.检查本机服务器类型&#xff0c;有的是x64&#xff0c;有的是ARM&#xff0c;先查清楚是什么类型再进行下载&#xff0c;否则会存在编译出错的问题 bash: /opt/node-v14.16.0-linux-x6…

基于YOLOv8深度学习的智慧农业猪行为检测系统研究与实现(PyQt5界面+数据集+训练代码)

随着智慧农业的快速发展&#xff0c;畜牧业的智能化管理已逐渐成为提高生产效率、提升动物福利、降低运营成本的关键手段之一。在此背景下&#xff0c;畜牧场对动物行为的自动化监测需求日益增长&#xff0c;尤其是在大型养猪场&#xff0c;猪群的日常行为检测对于疾病预防、饲…

独立资源池与共享资源池在云计算中各自的优势

在云计算领域&#xff0c;独立资源池和共享资源池是两种关键的资源管理策略&#xff0c;它们各自具有独特的优势&#xff0c;以适应不同的业务需求和场景。 独立资源池的优势 资源独占性&#xff1a;独立资源池为特定应用或用户提供专属的资源&#xff0c;这意味着资源不会被其…

异或和之和

//暴力做法 枚举每个子区间 O(n^3) //优化1 利用前缀异或和快速求出区间异或和 O(n^2) //优化2 处理位运算的常用方法&#xff1a;拆位法 常用的思想&#xff1a;贡献法思想 下面详见优化2&#xff1a; 1.拆位贡献法 2.实战真题1 题目链接&#xff1a;1.异或和之和 - 蓝桥…

【金融风控项目-07】:业务规则挖掘案例

文章目录 1.规则挖掘简介2 规则挖掘案例2.1 案例背景2.2 规则挖掘流程2.3 特征衍生2.4 训练决策树模型2.5 利用结果划分分组 1.规则挖掘简介 两种常见的风险规避手段&#xff1a; AI模型规则 如何使用规则进行风控 **使用一系列逻辑判断(以往从职人员的经验)**对客户群体进行区…

第8章硬件维护-8.2 可维护性和可靠性验收

8.2 可维护性和可靠性验收 可维护性和可靠性验收非常重要&#xff0c;硬件维护工程师在后端发现问题后&#xff0c;总结成可维护性和可靠性需求&#xff0c;在产品立项的时候与新特性一起进行需求分析&#xff0c;然后经过设计、开发和测试环节&#xff0c;在产品中落地。这些需…

在k8s上部署minio

一、 环境 已部署k8s&#xff0c;支持helm部署 二、添加Minio Helm Chart仓库 helm repo add bitnami https://charts.bitnami.com/bitnami -n your_namespace helm repo update -n your_namespace部署带tls的minio helm install minio-s3 bitnami/minio -n your_namespace…

gtest 框架

基本了解 google提供的一个C测试框架&#xff0c;主要就是简化测试单元的书写&#xff0c;具有高效、灵活可拓展的特点 主要特点 简单易用&#xff1a;gtest 提供了清晰且易于使用的 API&#xff0c;便于开发者快速编写单元测试。丰富的断言支持&#xff1a;gtest 提供了多种断…

机器学习—误差分析

帮助运行诊断的最重要的方法是选择下一步要尝试的内容&#xff0c;提高你的学习算法性能&#xff0c;偏差和方差可能是最重要的想法&#xff0c;然后是错误分析。 假设Mcv500&#xff0c;即有500个交叉验证示例&#xff0c;你的算法错误的分类了100个&#xff0c;错误分析过程…

微知-如何查看BlueField DPU上的内存信息,包括内存主频和位宽?(dmidecode -t memory)

背景 在定位DPU上网卡性能的时候&#xff0c;可能涉及到查看内存的主频、位宽、电压等信息&#xff0c;如何快速查看&#xff1f; 命令 dmidecode -t memory实操 可以看到主频是 3200MT/s&#xff0c;另外还能看到位宽&#xff0c;大小&#xff0c;电压等信息。

【AI系统】AI系统架构的组成

AI 系统组成 如图所示&#xff0c;大致可以将 AI 系统分为以下几个具体的方向&#xff1a; AI 训练与推理框架 AI 框架不仅仅是指如 PyTorch 等训练框架&#xff0c;还包括推理框架。其负责提供用户前端的 AI 编程语言&#xff0c;接口和工具链。负责静态程序分析与计算图构建…

竞赛思享会 | 2024年第十届数维杯国际数学建模挑战赛D题【代码+演示】

Hello&#xff0c;这里是Easy数模&#xff01;以下idea仅供参考&#xff0c;无偿分享&#xff01; 题目背景 本题旨在通过对中国特定城市的房产、人口、经济、服务设施等数据进行分析&#xff0c;评估其在应对人口老龄化、负增长趋势和极端气候事件中的韧性与可持续发展能力。…

机器学习基础07

目录 1.逻辑回归 1.1原理 1.2API 2.K-Means 2.1算法过程 2.2API 3.SVM&#xff08;支持向量机&#xff09; 3.1算法原理​ 3.2API 1.逻辑回归 逻辑回归(Logistic Regression)是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法。 1.1原理 逻辑回归的输…

基于python的在线投票系统小程序u9t2g.

目录 项目介绍开发技术具体实现截图微信开发者工具介绍技术路线开发语言以及框架介绍python-flask核心代码部分展示python-django核心代码部分展示详细视频演示源码获取 项目介绍 投票系统用户端是基于微信小程序&#xff0c;管理员端是基于web网页端&#xff0c; &#xff0c…

android 使用MediaPlayer实现音乐播放--权限请求

在Android应用中&#xff0c;获取本地音乐文件的权限是实现音乐扫描功能的关键步骤之一。随着Android版本的不断更新&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用需要动态请求权限&#xff0c;而到了android 13以上需要的权限又做了进一步…

向量数据库FAISS之五:原理(LSH、PQ、HNSW、IVF)

1.Locality Sensitive Hashing (LSH) 使用 Shingling MinHashing 进行查找 左侧是字典&#xff0c;右侧是 LSH。目的是把足够相似的索引放在同一个桶内。 LSH 有很多的版本&#xff0c;很灵活&#xff0c;这里先介绍第一个版本&#xff0c;也是原始版本 Shingling one-hot …