【算法】滑动窗口——长度最小的子数组

devtools/2024/9/23 16:14:53/

本篇文章是用一个实例来介绍常用算法之一“滑动窗口”的相关概念,有需要借鉴即可。

目录

  • 1.题目
  • 2.暴力求解
    • 2.1暴力求解思路:
    • 2.2时间复杂度是多少?
  • 3.暴力求解的优化
    • 3.1固定left的情况下,优化right的次数。
    • 3.2sum求值优化
    • 3.3不同组之间left与right包含关系的优化
  • 4.滑动窗口算法
    • 4.1概念
    • 4.2应用场景
    • 4.3使用
    • 4.4正确性
    • 4.5时间复杂度
  • 5.题解代码示例

1.题目

想要介绍一个算法,没有具体的例子来说算法是非常抽象的,算法是一种思想,因而为了介绍有关滑动窗口的概念,用下面例子来做相关介绍。

题目链接:LINK
在这里插入图片描述
看到这个题目我们先不论什么是“滑动窗口”这种算法,我们先从最简单的暴力求解来思考,顺着暴力求解的思路一步一步优化,最终达到“滑动窗口”的算法效果。

2.暴力求解

2.1暴力求解思路:

两个指针,一个left,一个right,加上left和right之间的所有数跟target进行比较,找到最小的len即可。

我们以上面的题目为例子,以题目中示例1为具体的操作对象:

left和right的组合共有36种情况,如下图所示:
在这里插入图片描述

2.2时间复杂度是多少?

答:left和right两层循环并且求sum时候需要再遍历一次,所以是N^3

当然这种代码很挫哈,为了提高效率,我们引出“滑动窗口”这一算法思想。

3.暴力求解的优化

滑动窗口是一种高效的算法,说白了也是从暴力求解的思路中优化过来的,所以我们一步一步来优化该暴力求解思路,来更加高效。

3.1固定left的情况下,优化right的次数。

在同一个left的情况下,很多时候right是多余的。比如说2 + 3 + 1 + 2 = 8早就超过target = 7了,暴力求解还在继续向后加…这很多余。
在这里插入图片描述

3.2sum求值优化

求和的时候,每次left和right变的情况下都要重新计算,十分耗费性能。我们想是不是可以利用一下上一次的sum值来求这次的sum值?
在这里插入图片描述
经过优化,这样就基本接近滑动窗口算法了。但还不是。这时的时间复杂度是O(N^2)
在本题中大概优化到下面效果:
在这里插入图片描述

大概就是下面的代码:

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int ret = INT_MAX;int n = nums.size();// 枚举出所有满⾜和⼤于等于 target 的⼦数组[start, end]// 由于是取到最⼩,因此枚举的过程中要尽量让数组的⻓度最⼩// 枚举开始位置for (int start = 0; start < n; start++){int sum = 0; // 记录从这个位置开始的连续数组的和// 寻找结束位置for (int end = start; end < n; end++){sum += nums[end]; // 将当前位置加上if (sum >= target) // 当这段区间内的和满⾜条件时{// 更新结果,start 开头的最短区间已经找到ret = min(ret, end - start + 1);break;}}}// 返回最后结果return ret == INT_MAX ? 0 : ret;}
};

不用怀疑,力扣过不了哈。
在这里插入图片描述

3.3不同组之间left与right包含关系的优化

这个是什么意思呢?
嗯…经过上面所说的两步之后,我们就发现以上面的题目来举例,暴力求解就可以达到下面这种优化效果:
在这里插入图片描述
当然,上面超出时间限制截图告诉我们,继续优化…
但是我们发现一个问题,比如拿下面的例子来说(看蓝色框)
在这里插入图片描述
放大一点:
在这里插入图片描述
就是这种不满足的包含情况下也可以优化掉。
下面是真正的滑动窗口优化图:
在这里插入图片描述

4.滑动窗口算法

4.1概念

基于双指针算法,两指针同向向前且不回退的算法思想。

4.2应用场景

具有一定单调性题目,比如在本节博客的举的这道题种,从left到right不断加就是一种单增关系。

4.3使用

滑动窗口的大体使用步骤是什么呢?

  • 1.left,right
  • 2.进窗口
  • 3.判断
    • 出窗口
    • 更新结果

注:①2、3两步是循环;②本步骤只是大体步骤;

比如说,在本例子中,这个步骤就可以具体为:
在这里插入图片描述

  • 1.先让left = 0,right = 0;
  • 2.进窗口,sum +=2;
  • 3.判断sum < target;
  • 4.所以继续进窗口,让right = 1,sum+=3;
  • 5.继续判断,sum = 5 < target
  • 6.继续进窗口,right = 2,sum+=1
  • 7.继续判断,sum = 6 < target
  • 8.继续进窗口,right = 3,sum+=2
  • 9.继续判断,sum = 8 > target
  • 10.满足条件,出窗口
  • 11.left++,left = 1,sum-=2
  • 12.判断sum = 6 < target
  • 13.right++,right = 4,sum+=4
  • 14.判断sum = 10 > target
  • 。。。

4.4正确性

滑动窗口算法对吗?是正确的。
因为只是在暴力求解的基础上去掉了一些不必要的计算过程。

4.5时间复杂度

对于上面那道题来说,暴力求解是O(N^3),但是滑动窗口是O(N)

5.题解代码示例

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int ret = INT_MAX;int n = nums.size();int sum = 0;for(int left = 0,right = 0;right < n;right++){sum+=nums[right];//进窗口while(sum>=target)//判断{ret = min(ret,right - left + 1);sum-=nums[left];//出窗口left++;//持续判断}}// 返回最后结果return ret == INT_MAX ? 0 : ret;}
};

EOF


http://www.ppmy.cn/devtools/36343.html

相关文章

docker安装Debian:11 freeswitch1.10.5

文章目录 一、生成一个镜像二、切换一个镜像源为阿里源三、安装一些相关依赖和freeswitch3.1第一步&#xff1a;安装freeswitch-mod和下载所需的依赖项3.2 设置密钥3.3 安装freeswitch所需的依赖项3.4 报错3.4.1 报错13.4.2 报错23.4.3 报错3 四、运行4.1 通话三十秒自动挂断 一…

go动态创建/增加channel并处理数据

背景描述 有一个需求&#xff0c;大概可以描述为&#xff1a;有多个websocket连接&#xff0c;因此消息会并发地发送过来&#xff0c;这些消息中有一个标志可以表明是哪个连接发来的消息&#xff0c;但只有收到消息后才能建立channel或写入已有channel&#xff0c;在收消息前无…

相机内存卡格式化怎么恢复?恢复数据的3个方法

相机内存卡格式化后&#xff0c;许多用户都曾面临过照片丢失的困境。这些照片可能具有极高的纪念价值&#xff0c;也可能包含着重要的信息。因此如何有效地恢复这些照片变得至关重要。本文将详细介绍三种实用的恢复方法&#xff0c;帮助您找回那些珍贵的影像。 下面分享几个实…

引导网络配置文件(Bootstrap profiles)

有任何关于GSMA\IOT\eSIM\RSP\业务应用场景相关的问题&#xff0c;欢迎W: xiangcunge59 一起讨论, 共同进步 (加的时候请注明: 来自CSDN-iot). 商业锁定&#xff08;commercial lock-in&#xff09;是eUICC技术中可能遇到的一种情况&#xff0c;它对IoT项目的运营商成本和灵…

Java学习之线程

线程&#xff1a; 1. 单线程与多线程的运行 public class DemoThread {public static void main(String[] args) {/*TODO 构建多线程模式方式1: 自定义类继承 Tread类并重写其run方法在run方法中定义当前线程需要完成的任务逻辑*//*TODO 多线程的调用1.构建对象,并直接使用其…

# Maven 下载安装与配置

Maven 下载安装与配置 一、前言&#xff1a; 1、Maven 简介&#xff1a; Apache Maven是一个&#xff08; 特别是 Java 编程 &#xff09;项目管理及自动构建工具&#xff0c;由 Apache 软件基金会所提供。基于项目对象模型&#xff08; 缩写&#xff1a;POM &#xff09;概念…

STM32F103学习笔记 | 8. 二,八,十,十六进制表示方式

文章目录 进制基本信息参考文献 进制基本信息 C语言中的表示&#xff0c;前缀加0表示八进制数&#xff0c;前缀加0x表示十六进制数 基数数码名称描述代码和书本中的表示举例20 和 1二进制逢二进一&#xff0c;几乎所有的电子计算机内部都使用二进位制&#xff0c;分别为“0”…

eMMC断电通知机制(PON)

概述 PON: POWER_OFF_NOTIFICATION host在断电前通知eMMC卡要断电了,然后eMMC把没有做完的操作赶紧做完,然后host再进行断电。 场景: (1).host在把VCCQ和VCC这两路电源断电之前,应该发布PON(POWER_OFF_LONG/POWER_OFF_SHORT)。 (2).设备正在进入sleep state时候,h…