LeetCode——滑动窗口(初阶)

LeetCode——滑动窗口(初阶)

文章目录

简要介绍

我们的滑动窗口算法是我们在笔试面试以及算法竞赛中都比较常见的一种算法,这个算法通常都是用来处理我们的数组和字符串问题的,尤其适合寻找出某个条件的子数组或是子字符串的问题或者是用在了连续子问题的计算之中。

我们的滑动窗口从名字来看就知道了,我们要做的就是来维护一个叫“滑动窗口”的东西(bushi),这个窗口(可以理解成一段区间)的大小可以是固定的也可以是变化的,这个窗口在我们的数据结构上面移动(“滑动”)来扫描我们的结构。

下面我们来介绍一下我们的滑动窗口的基本套路:

1、进窗口。

2、判断条件(跟据题意分析)。

3、更新我们要的结果。

4、出窗口。

相关例题

长度最小的子数组

题目描述

给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其总和大于等于 target 的长度最小的 子数组[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度**。**如果不存在符合条件的子数组,返回 0

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。 

示例 2:

输入:target = 4, nums = [1,4,4] 输出:1 

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0 

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 104

进阶:

  • 如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

题目分析

我们这个题目是一个典型的可以使用我们滑动窗口的题目,我们一开始就可以想到我们的暴力写法(遍历数组两次),但是时间复杂度是O(n2)**这里的长度是10的5次方,所以这里是10的10次方大于了**108会超时,所以我们这里需要优化我们的遍历,一般的优化都是像我们的O(log n)和O(n)的方向靠近,其实如果学过前缀和数组的,这个题目可以用预处理前缀和来做,然后二分查找即可,这个复杂度就是O(log n),但是其实我们这个题目有一个**O(n)**的算法,那就是我们的滑动窗口了。

实现思路💡

我们这里的实现思路本质上就是维护一个滑动窗口,这个窗口里面的值要小于我们的目标值,实现过程如下:

1、定义两个指针,一个指向了我们的开头,一个还是指向了我们的开头并且还要定义一个长度的最大值。

2、接下来就是窗口的维护了:

a、首先就是要进窗口(将右指针当前值加入)。

b、判断是不是大于等于了我们的目标值,如果是就更新我们的结果,然后将我们将我们的左指针指向的值出窗口(实现我们的向右滑动)。

c、右指针右移一位。

实现代码

classSolution{public:intminSubArrayLen(int target, vector<int>& nums){int n=nums.size(),sum=0,len=INT_MAX;for(int left=0,right=0;right<n;right++){ sum+=nums[right];//进窗口while(sum>=target){ len=min(len,right-left+1);//判断 sum-=nums[left++];//出窗口}}return len==INT_MAX?0:len;}};

无重复字符的最长子串

题目描述

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

示例 1:

输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。 

示例 2:

输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 

示例 3:

输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

题目分析

题目问的是找特征字串,我们可以想到是是用的滑动窗口来解决的,只不过这里的约束条件和之前的不一样而已,之前的哪个题目是要的窗口里面的值要小于目标值,这里的要求则是要维护一个没有重复字符的子串,其实本质还是一样的。

实现思路💡

首先就是要有我们的哈希表(这里既可以使用unordered_map,也可以使用数组下标),然后就是两个指针都指向了开头,同时我们还要定义一个长度的最小值。

然后就是滑动窗口了,移动我们的右指针,将加入窗口的字符的哈希值++,紧接着就是我们的判断条件:如果我当前加入的字符的哈希值大于了1,说明我们窗口里面已经有了重复的字符了,于是我们就可以将我们的左值出窗口了直到我们的窗口满足条件。判断了之后我们就要更新我们的长度的最大值,并将右指针右移。

最后就是我们的返回条件,如果我们的长度是最开始的值就返回我们的0,不是就直接返回即可。

实现代码

classSolution{public:intlengthOfLongestSubstring(string s){ unordered_map<char,int> hash;int n = s.size();int len =-1;for(int i =0, j =0; j < n;){ hash[s[j]]+=1;while(hash[s[j]]>1){ hash[s[i++]]--;} len =max(len, j - i +1); j++;}return len ==-1?0: len;}};

最大连续1的个数 III

题目描述

给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k0 ,则返回执行操作后 数组中连续 1 的最大个数

示例 1:

输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2 输出:6 解释:[1,1,1,0,0,1,1,1,1,1,1] 粗体数字从 0 翻转到 1,最长的子数组长度为 6。 

示例 2:

输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3 输出:10 解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] 粗体数字从 0 翻转到 1,最长的子数组长度为 10。 

提示:

  • 1 <= nums.length <= 105
  • nums[i] 不是 0 就是 1
  • 0 <= k <= nums.length

题目分析

其实这个题目我们可以换一个思路来理解,这个问题可以转换成求一个最长区间这个区间里面0的个数不超过k个(毕竟数字是二进制的,只有两个值0和1),所以这个时候就变成了求某特征区间了,于是乎我们就可以想到使用滑动数组来实现。

实现思路💡

其实这里的实现思路和之前两个都十分地相似,我们先要定义两个指针都是指向我们的最左端的,并且设置我们的长度最小值。

循环中,我们要判断当前值是不是0,是的话就将当前的0值计数++,然后我们判断我们的0值是不是大于了我们的k值,大于的话我们就将我们的左值右移并将计数--,再然后就是更新我们的最终答案了。

最后就是我们的返回值判断,如果值是开始的值没变就返回0,否则直接返回即可。

实现代码

classSolution{public:intlongestOnes(vector<int>& nums,int k){int n = nums.size();int cnt =0;int ret =-1;for(int i =0, j =0; j < n; j++){if(nums[j]==0){ cnt++;}while(cnt > k){if(nums[i++]==0){ cnt--;}} ret =max(ret, j - i +1);}return ret ==-1?0: ret;}};

将 x 减到 0 的最小操作数

题目描述

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1

示例 1:

输入:nums = [1,1,4,2,3], x = 5 输出:2 解释:最佳解决方案是移除后两个元素,将 x 减到 0 。 

示例 2:

输入:nums = [5,6,7,8,9], x = 4 输出:-1 

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10 输出:5 解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。 

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 104
  • 1 <= x <= 109

题目描述

这个题目其实还是具有很强的迷惑性,我们可以将这个题目也转化一下,其实它问的是求一个最长的区间,区间里面的值等于我们原来数组的和减去我们的x,这个时候我们就变成了求最长区间的和等于目标值,这个时候我们求的就是特征子数组,我们就可以使用滑动窗口来实现了。

实现思路💡

我们这里的第一步就是求我们的目标值,其实就是计算数组的和然后再减去我们的x即可,这个时候我们需要做一个特判,如果减到了小于0就要返回-1。

然后我们就需要定义两个指针来指向我们的最左端并设置我们的长度最小值。

进入循环后,我们将右指针的值加入窗口,紧接着就是窗口条件的判断:大于了目标值就要将左指针指向的值出窗口;跳出循环后我们需要更新我们的结果。

最后,就是我们的返回值判断,当我们的返回值还是开始的值的时候就返回-1,反之就返回数组长度减去我们设置的长度。

实现代码

classSolution{public:intminOperations(vector<int>& nums,int x){int n = nums.size();int k =0;for(auto s : nums){ k += s;} k -= x;if(k <0)return-1;int len =-1;int sum =0;for(int i =0, j =0; j < n; j++){ sum += nums[j];// 进窗口while(sum > k){ sum -= nums[i++];// 出窗口}if(sum == k){ len =max(len, j - i +1);}}return len ==-1?-1: n - len;}};

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk