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

算法学习--滑动窗口

目录

滑动窗口

是什么?

核心思想

实际案例分享

长度最小子数组

无重复字符的最长长度

定长子串元音的最大数目 

子数组最大平均数I


推荐一篇很牛的文章:讨论 - 力扣(LeetCode)

滑动窗口

是什么?

滑动窗口(Sliding Window)是一种高效的算法技巧,常用于数组或字符串的问题中,用于寻找满足特定条件的子数组或子串

核心思想

可以简单理解为快慢指针的变种。

  1. 使用两个指针(通常是 left 和 right )定义一个“窗口”。
  2. right 指针向右扩展窗口,添加新元素。
  3.  当窗口不满足条件时, left 指针向右移动,缩小窗口。
  4. 通过这种方式,避免重复计算,实现O(n)时间复杂度。每次添加或删除元素的时间复杂度都是O(1)

实际案例分享

长度最小子数组

题目来源:209. 长度最小的子数组 - 力扣(LeetCode)

 首个题解:

class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:res = float('inf')left = 0for right in range(len(nums)):while sum(nums[left : right + 1]) >= target:res = min(right + 1 - left,res)left += 1res = 0 if res == float('inf') else resreturn res 

Solution (O(n²) 时间复杂度) :在 while 循环内每次调用 sum(nums[left : right + 1]) ,这会重新计算整个子数组的和,导致嵌套循环,时间开销巨大。当 n=10^5 时,可能超时。

所以退化成了暴力破解

知识点:内置函数在数组数据很大时会很耗时

正解:

Solution (O(n) 时间复杂度) :使用累积和 s 维护窗口和,每次滑动只加减一个元素,高效。

class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:res = float('inf')s = left = 0for right in range(len(nums)):s += nums[right]while s >= target:res = min(right + 1 - left,res)s -= nums[left]left += 1res = 0 if res == float('inf') else resreturn res 

无重复字符的最长长度

题目来源:3. 无重复字符的最长子串 - 力扣(LeetCode)

解:

class Solution:def lengthOfLongestSubstring(self, s: str) -> int:res = 0left = 0no_double = []if len(s) == 1:return 1for right,s_ in enumerate(s):while s_ in no_double:no_double.remove(s[left])left += 1res = max(res,right + 1 - left)no_double.append(s_)return res

思路:

  1. 利用左右端点动态滑动窗口
  2. 如果该窗口内不存在重复字符,那么右端点右移(将该字符加入容器
  3. 如果该窗口内存在重复字符,那么左端点右移从容器中删除左端点对应的字符,左端点➕1
  4. 注意:字符需要存储在一个容器中,这里我使用的是列表 in 操作判断是否已经存在,如果是那么就是在右端点右移后出现了重复字符

心得:

不是所有程序都可以一边写对,所以在有思路之后应该尝试coding,并不断debug修改直到完成!

优解:

利用计数器哈希表,记录每个字符出现的次数,如果次数大于等于2就是重复了,需要去重并右移端点

class Solution:def lengthOfLongestSubstring(self, s: str) -> int:res = 0left = 0cnt = Counter()for right,s_ in enumerate(s):cnt[s_] += 1while cnt[s_] >= 2:cnt[s[left]] -= 1left += 1res = max(res,right + 1 - left)return res

定长子串元音的最大数目 

题目来源:1456. 定长子串中元音的最大数目 - 力扣(LeetCode)

我的分析:

  1. 滑动窗口定长为k,使用两个指针标记窗口的左右端点,那么两个端点之间的长度应该为k,即right - left + 1 = k,由此可以推导left = right + 1 - k
  2. 滑动窗口我习惯让右端点遍历滑动,所以第一点公式基于此
  3. 由于需要记录窗口内的元音个数,当时脑子捋顺不过来了,就使用tmp存储窗口内元音数量,然后每更新一次就添加到ans列表,最后返回max(ans)
  4. 滑动窗口关键点就是如何移动,如何移除,所以不可能不调试就能一次写完的,除非像灵茶山这样的大佬,要利用好本地的debug工具梳理逻辑,然后修改不断完善并最终实现移动移除操作

我的解:

class Solution:def maxVowels(self, s: str, k: int) -> int:yuan = 'aeiou'left = 0ans = []tmp = 0 for right in range(len(s)):if s[right] in yuan:tmp += 1left = right +1 - kif left < 0:continueans.append(tmp)   #这里可以直接 ans = max(ans,tmp)当时脑子抽抽了if s[left] in yuan:tmp -= 1return max(ans)

大佬的解答:

class Solution:def maxVowels(self, s: str, k: int) -> int:ans = vowel = 0for i, c in enumerate(s):if c in "aeiou":vowel += 1if i < k - 1:  continueans = max(ans, vowel)if s[i - k + 1] in "aeiou":vowel -= 1return ans
作者:灵茶山艾府

总结:

其实我的代码结构是没问题的,但是在写代码过程中脑子有点小乱,所以没有及时发现max(ans,tmp)方法

子数组最大平均数I

题目来源:643. 子数组最大平均数 I - 力扣(LeetCode)

我的分析:

  1. 定长滑动窗口,加数----->更新ans----->移除末尾数
  2. 需要注意的是,整数数组中存在负数,所以ans定义不能是0然后使用max获取,而是要定义为无穷小,即-inf或-float('inf') 

我的解:

class Solution:def findMaxAverage(self, nums: List[int], k: int) -> float:ans = -float('inf')left = 0tmp = 0for right in range(len(nums)):tmp += nums[right]left = right + 1 - kif left < 0:continueans = max(ans,tmp/k)tmp -= nums[left]return ans

http://www.dtcms.com/a/292504.html

相关文章:

  • 学习python中离线安装pip及下载package的方法
  • C语言:函数基础
  • day059-zabbix自定义监控与自动发现
  • Node.js:Web模块、Express框架
  • es6中的symbol基础知识
  • 在Android开发中,如何获取到手机设备的PIN码?
  • 如何安装CMake较新的版本
  • Apache Ignite 长事务终止机制
  • 精密全波整流电路(一)
  • torchvision.transforms 与 MONAI 数据增强的异同
  • Cloud 与 VPS 的区别:如何选择最适合你的服务器解决方案?
  • stream流入门
  • 【打怪升级 - 01】保姆级机器视觉入门指南:硬件选型 + CUDA/cuDNN/Miniconda/PyTorch 安装全流程(附版本匹配秘籍)
  • vmware 克隆虚拟机,报错:克隆时出错:指定不存在的设备。然后电脑卡死,只能强制关机再开机。
  • FastDFS 6.11.0 单机环境搭建与测试(附 Nginx 集成)+ docker构建+k8s启动文件
  • 用org.apache.pdfbox 转换 PDF 到 图片格式
  • KafkaMQ 日志采集最佳实践
  • Python 正则表达式:入门到实战
  • 日常随笔-React摘要
  • 【ROS/DDS】FastDDS :编写FastDDS程序实现与ROS2 通讯(四)
  • 深入浅出理解 TCP 与 UDP:网络传输协议的核心差异与应用
  • 平台端用户管理功能设计全解:从分类管控到审核闭环
  • 基于springboot的疫苗发布和接种预约系统(论文+开题报告)
  • 实现分布式锁
  • 腾讯云SDK
  • 论文笔记:Parameter Competition Balancing for Model Merging
  • MongoDB频繁掉线频繁断开服务的核心原因以及解决方案-卓伊凡|贝贝|莉莉|糖果
  • 在Windows 10/11上使用Qt和SOEM构建EtherCAT主站:工业控制新纪元
  • 【Axure视频教程】形状地图
  • Qt 事件处理机制深入剖析