当前位置:首页 > 算法 > 正文内容

【算法】滑动窗口1—窗口大小固定

亿万年的星光7个月前 (02-22)算法1134

一、定义

滑动窗口算法(Sliding Window Algorithm)是一种用于解决数组或字符串中子数组或子串问题的优化技术。它通过维护一个窗口(通常是数组或字符串的一个连续子区间),在遍历过程中动态调整窗口的起始和结束位置,从而高效地解决问题。

滑动窗口的核心思想是:

  • 窗口大小固定:窗口的大小在滑动过程中保持不变。

  • 窗口大小可变:窗口的大小根据条件动态调整。


二、使用场景

滑动窗口算法通常用于以下场景:

  1. 1.子数组/子串问题:

    • 求满足条件的最大或最小子数组/子串。

    • 例如:最大子数组和、最小覆盖子串、最长无重复字符子串等。

  2. 2.固定窗口大小问题:

    • 例如:计算大小为 k 的子数组的平均值。

  3. 3.优化暴力解法:

    • 将时间复杂度从 O(n²) 优化到 O(n)


三、示例


1.例题1:固定窗口大小



【题目描述】给定一个数组和一个整数 k,计算所有大小为 k 的子数组的平均值。

【题目分析】

(1) 什么是子数组?

  • 子数组是数组中连续的一段元素。

  • 例如,数组 [1, 3, 2, 6, -1] 的子数组包括 [1, 3, 2][3, 2, 6] 等。

(2)什么是大小为 k 的子数组?

  • 大小为 k 的子数组是指长度为 k 的连续子数组。

  • 例如,如果 k = 3,那么子数组的长度必须是 3。

(3)什么是子数组的平均值?

  • 子数组的平均值是指子数组中所有元素的和除以子数组的长度。

  • 例如,子数组 [1, 3, 2] 的平均值是 (1 + 3 + 2) / 3 = 2

(4)问题的目标

  • 对于数组中的每一个大小为 k 的子数组,计算其平均值,并返回所有平均值的集合。


【解题思路】

(1)暴力解法

  • 遍历数组,对于每一个起始位置 i,计算从 i 到 i + k - 1 的子数组的和,然后除以 k 得到平均值。

  • 时间复杂度:O(n * k),其中 n 是数组的长度。

(2)滑动窗口优化

  • 使用滑动窗口技术,避免重复计算子数组的和。

  • 初始化第一个窗口的和,然后在滑动窗口时,加上新元素,减去旧元素。

  • 时间复杂度:O(n)

#include <iostream>
using namespace std;
void sw(int nums[], int n, int k) {
    if (n < k) return; // 如果数组长度小于k,直接返回
    double windowSum = 0;
    // 初始化窗口
    for (int i = 0; i < k; i++) {
        windowSum += nums[i];
    }
    cout << windowSum / k << " ";
    // 滑动窗口
    for (int i = k; i < n; i++) {
        windowSum += nums[i] - nums[i - k]; // 加上新元素,减去旧元素
        cout << windowSum / k << " ";
    }
    cout << endl;
}

int main() {
    int nums[] = {1, 3, 2, 6, -1, 4, 1, 8, 2};
    int n = sizeof(nums) / sizeof(nums[0]);
    int k = 5;
    sw(nums, n, k);
    return 0;
}


【过程解释】

  1. 初始化窗口:

    • 计算第一个窗口的和 windowSum,即 nums[0] 到 nums[k-1] 的和。

    • 输出第一个窗口的平均值 windowSum / k

  2. 滑动窗口:

    • 从第 k 个元素开始,滑动窗口。

    • 每次滑动时,加上新元素 nums[i],减去旧元素 nums[i - k]

    • 输出当前窗口的平均值 windowSum / k



图示:

第一次:(1+3+2)/3 




第二次:(3+2+6)/3 ,对比上一次,少了第一个数1,多了后一个数6



第二次:(2+6-1)/3 ,对比上一次,少了上一个数2,多了后一个数-1




扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

分享给朋友:

相关文章

【算法】动态规划(一)

1.基本概念在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。因此各个阶段决策的选取不能任意确定,它依赖...

【贪心】区间覆盖

【贪心】区间覆盖

【题目描述】给定一个长度为m的区间,再给出n条线段的起点和终点(本题考虑闭区间),求最少使用多少线段可以将整个区间完全覆盖。【输入】第一行是区间长度m。第二行是n,表示有n个可选区间。后面跟着n行数据...

【贪心】 导弹拦截

【贪心】 导弹拦截

【题目描述】某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统,但是这种拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来...

【算法】高精度(1)

一、  什么是高精度高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算...

【贪心】区间调度

【贪心】区间调度

【题目描述】有n项工作,每项工作分别在si时间开始,在ti时间结束。对于每项工作,你都可以选择参与与否。如果选择了参与,那么自始至终都必须全程参与。此外,参与工作的时间段不能重叠(即使是开始与结束的瞬...

【贪心】----找零钱问题

一、找零钱问题例题1:有 1 元,5元,10元,20元,100元,200元的钞票无穷多张。现在使用这些钞票支付X元,最少需要多少张钞票。X = 628最佳支付方法:3张200块的,1张20块的,1张5...