【LeetCode刷题笔记(9-1)】【Python】【无重复字符的最长子串】【滑动窗口】【中等】

文章目录

  • 引言
  • 无重复字符的最长子串
    • 题目描述
    • 提示
  • 解决方案1:【滑动窗口】
  • 结束语

无重复字符的最长子串

引言

编写通过所有测试案例的代码并不简单,通常需要深思熟虑理性分析。虽然这些代码能够通过所有的测试案例,但如果不了解代码背后的思考过程,那么这些代码可能并不容易被理解和接受。我编写刷题笔记的初衷,是希望能够与读者们分享一个完整的代码是如何在逐步的理性思考下形成的。我非常欢迎读者的批评和指正,因为我知道我的观点可能并不完全正确,您的反馈将帮助我不断进步。如果我的笔记能给您带来哪怕是一点点的启示,我也会感到非常荣幸。同时,我也希望我的分享能够激发您的灵感和思考,让我们一起在编程的道路上不断前行~

无重复字符的最长子串

题目描述

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

示例 1:

  • 输入: s = “abcabcbb”
  • 输出: 3
  • 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

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

示例 3:

  • 输入: s = “pwwkew”
  • 输出: 3
  • 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。

提示

  • 答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

解决方案1:【滑动窗口】

根据题意,解决问题的关键是如何在字符串 s找到其中不含有重复字符最长子串长度。且根据提示,【子串】必须是索引连续的字符串。当脑海中没有明确idea时,分析示例可能会带来灵感~

  • 在示例3,字符串s="pwwkew",当我们从左往右遍历字符串时,遇到的第一个不含有重复字符的子串是"pw",此时最长子串长度max_len=2;随后,当遍历到第三个字符"w"时,出现了重复,此时应该舍弃"pw",从第三个字符"w"为起点,重新寻找第二个不含有重复字符的子串"wke", 此时最长子串长度max_len=3;最后,当遍历到最后一个字符"w"时,此时应该舍弃子串"wke"中的"w",让"ke"和最后一个字符"w"组成最后一个不含有重复字符的子串是"kew", 此时最长子串长度max_len=3

从示例3中,我们可以总结出以下规律:

  • 首先,我们需要选择一种能够方便获取元素长度数据结构存储当前“子串”,以便获取其长度来及时更新max_len
  • 其次,这种数据结构应具备查找元素的功能,以便判断新元素是否存在于当前子串中。
    • 若新元素存在当前子串 ⇒ 即将出现重复元素,如示例三的新元素"w"和当前子串"wke" ⇒ 需要先舍弃子串"wke"中的第一个元素"w",而这个被舍弃的"w"也是首先进入这种数据结构的字符 ⇒ 需要一种能够实现“先进先出”的数据结构 ⇒ 利用【队列】存储子串,当舍弃掉队列头部的"w"后,再把新的"w"添加到队列的尾部,组成新的子串"kew"
    • 若新元素不存在当前子串 ⇒ 直接把新元素添加到队列尾部即可。

问题1:在python中,什么数据对象可以实现【队列】这种数据结构?

列表

问题2:上面叙述的流程有没有一个约定俗成的算法名称?

有!滑动窗口法

由于队列中的元素个数是随着遍历字符串s不断增加/删除的,且队列的长度也在不断发生变化 ⇒ 我们可以将队列想象成一个不定长窗口,在字符串s上按照从左往右的顺序进行滑动滑动窗口法

完整代码如下

class Solution:  def lengthOfLongestSubstring(self, s: str) -> int:  # 用列表对象初始化一个空队列  queue = []  # 初始化最大长度为0  max_len = 0  # 遍历字符串s的每个字符  for c in s:  # 如果当前字符在队列中 ---> 出现重复while c in queue:  # 从队列的头部不断删除字符,直到当前字符不存在于队列中  queue.pop(0)  # 由于当前字符不存在于队列中,将当前字符添加到队列尾部queue.append(c)  # 如果队列的长度大于最大长度  if len(queue) > max_len:  # 更新最大长度为队列的长度  max_len = len(queue)  # 返回最大长度  return max_len

运行结果
在这里插入图片描述
问题3:从运行结果来看,似乎还有很大的优化空间,可以从哪些方面入手优化呢?

  1. 换一个查找速度更快的数据结构存储“子串”。

由于当前队列是基于列表进行实现的,而列表中查找元素的时间复杂度是O(n)。有没有查找元素的时间复杂度更低的数据结构,并且也能实现队列?

有!基于哈希表的集合对象set(),但需要额外的变量进行辅助。

完整代码如下

class Solution:  def lengthOfLongestSubstring(self, s: str) -> int:  # 如果字符串为空,返回0  if not s:  return 0  # 初始化变量  n = len(s)  look_up = set()  # 用于存储当前子字符串cur_len = 0  # 当前子字符串的长度  max_len = 0  # 最长子字符串的长度  left = 0  # 滑动窗口的左边界  # 遍历字符串  for i in range(n):  # 如果当前字符在已出现的字符集中,则需要移动左边界并缩小当前子字符串的长度  while s[i] in look_up:  look_up.remove(s[left]) # 队列移除头部元素,left指向的就是头部元素所在位置 cur_len -= 1  left += 1  # 将当前字符添加到字符集中,并增加当前子字符串的长度  look_up.add(s[i])  cur_len += 1  # 如果当前子字符串的长度大于最长子字符串的长度,则更新最长子字符串的长度  if cur_len > max_len:  max_len = cur_len# 返回最长子字符串的长度  return max_len

运行结果
在这里插入图片描述
问题4:从运行结果来看,已经有一定程度的优化,还能在进一步优化吗?

  1. 当最大无重复子串长度max_len已经大于当前子串长度cur_len和字符串s尚未遍历的元素个数n-i之和时,可以提前终止遍历,并返回结果。

完整代码如下

class Solution:  def lengthOfLongestSubstring(self, s: str) -> int:  # 如果字符串为空,返回0  if not s:  return 0  # 初始化变量  n = len(s)  look_up = set()  # 用于存储已经出现过的字符  cur_len = 0  # 当前子字符串的长度  max_len = 0  # 最长子字符串的长度  left = 0  # 滑动窗口的左边界  # 遍历字符串  for i in range(n):  # 如果当前字符在已出现的字符集中,则需要移动左边界并缩小当前子字符串的长度  while s[i] in look_up:  look_up.remove(s[left])  cur_len -= 1  left += 1  # 将当前字符添加到字符集中,并增加当前子字符串的长度  look_up.add(s[i])  cur_len += 1  # 如果当前子字符串的长度大于最长子字符串的长度,则更新最长子字符串的长度  if cur_len > max_len:  max_len = cur_len# 最大无重复子串长度max_len已经大于等于当前子串长度cur_len和字符串s尚未遍历的元素个数n-i之和时,退出for循环if cur_len + (n-i) <= max_len:break  # 返回最长子字符串的长度  return max_len

运行结果
在这里插入图片描述
复杂度分析

  • 时间复杂度:O(N),其中 N 是字符串s元素的数量。
  • 空间复杂度:参考官方题解

结束语

  • 亲爱的读者,感谢您花时间阅读我们的博客。我们非常重视您的反馈和意见,因此在这里鼓励您对我们的博客进行评论。
  • 您的建议和看法对我们来说非常重要,这有助于我们更好地了解您的需求,并提供更高质量的内容和服务。
  • 无论您是喜欢我们的博客还是对其有任何疑问或建议,我们都非常期待您的留言。让我们一起互动,共同进步!谢谢您的支持和参与!
  • 我会坚持不懈地创作,并持续优化博文质量,为您提供更好的阅读体验。
  • 谢谢您的阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql:查看线程缓存中的线程数量

使用命令show global status like Threads_cached;可以查看线程缓存中的线程数量。 例如&#xff0c;查询线程缓存中的线程数量如下&#xff1a; 然后启动应用程序&#xff0c;使用连接&#xff0c;查询如下&#xff1a; 由查询结果可以看到&#xff0c;线程缓存中的线程数量…

【算法系列篇】递归、搜索和回溯(四)

文章目录 前言什么是决策树1. 全排列1.1 题目要求1.2 做题思路1.3 代码实现 2. 子集2.1 题目要求2.2 做题思路2.3 代码实现 3. 找出所有子集的异或总和再求和3.1 题目要求3.2 做题思路3.3 代码实现 4. 全排列II4.1 题目要求4.2 做题思路4.3 代码实现 前言 前面我们通过几个题目…

独立站退款率太高会怎么样?如何解决独立站退款纠纷?——站斧浏览器

独立站退款率太高会怎么样&#xff1f; 当独立站的退款率过高时&#xff0c;可能会对卖家和平台产生一些负面影响&#xff1a; 信誉受损&#xff1a;退款率过高可能会导致卖家的信誉受损。买家在购物时通常倾向于选择评价好的卖家&#xff0c;高退款率可能会让卖家的评价下降…

在vue中通过js动态绘制table,并且合并连续相同内容的行,支持点击编辑单元格内容

首先是vue代码 <template><div id"body-container"style"position: absolute"><div class"box-container"><div class"lsb-table-box" ><div class"table-container" id"lsb-table"&…

PyTorch深度学习实战(26)——卷积自编码器(Convolutional Autoencoder)

PyTorch深度学习实战&#xff08;26&#xff09;——卷积自编码器 0. 前言1. 卷积自编码器2. 使用 t-SNE 对相似图像进行分组小结系列链接 0. 前言 我们已经学习了自编码器 (AutoEncoder) 的原理&#xff0c;并使用 PyTorch 搭建了全连接自编码器&#xff0c;但我们使用的数据…

node.js mongoose middleware

目录 官方文档 简介 定义模型 注册中间件 创建doc实例&#xff0c;并进行增删改查 方法名和注册的中间件名相匹配 执行结果 分析 错误处理中间件 手动抛出错误 注意点 官方文档 Mongoose v8.0.3: Middleware 简介 在mongoose中&#xff0c;中间件是一种允许在执…

vue的自定义指令注册使用

目录 分类 局部注册 全局注册 使用例子 分类 自定义指令的注册分为局部注册和全局注册 局部注册是在某个组件内注册的指令&#xff0c;只能在这个组件内使用 全局注册是在main.js中注册的指令在任何组件内都可以使用&#xff0c;指令在使用时不论是全局还是局部注册的&am…

机器学习 | 贝叶斯方法

不同于KNN最近邻算法的空间思维&#xff0c;线性算法的线性思维&#xff0c;决策树算法的树状思维&#xff0c;神经网络的网状思维&#xff0c;SVM的升维思维。 贝叶斯方法强调的是 先后的因果思维。 监督式模型分为判别式模型和生成式模型。 判别模型和生成模型的区别&#xf…

Spring MVC框架支持RESTful,设计URL时可以使用{自定义名称}的占位符@Get(“/{id:[0-9]+}/delete“)

背景&#xff1a;在开发实践中&#xff0c;如果没有明确的规定URL&#xff0c;可以参考&#xff1a; 传统接口 获取数据列表,固定接口路径&#xff1a;/数据类型的复数 例如&#xff1a;/albums/select RESTful接口 - 根据ID获取某条数据&#xff1a;/数据类型的复数/{id} - 例…

智能化物联网(IoT):发展、问题与未来前景

导言 智能化物联网&#xff08;IoT&#xff09;作为信息技术领域的一项核心技术&#xff0c;正在深刻改变人们的生活和工作方式。本文将深入研究IoT的发展过程、遇到的问题及解决过程、未来的可用范围&#xff0c;以及在各国的应用和未来的研究趋势。探讨在哪些方面能够取得胜利…

将Abp默认事件总线改造为分布式事件总线

文章目录 原理创建分布式事件总线实现自动订阅和事件转发 使用启动Redis服务配置传递Abp默认事件传递自定义事件 项目地址 原理 本地事件总线是通过Ioc容器来实现的。 IEventBus接口定义了事件总线的基本功能&#xff0c;如注册事件、取消注册事件、触发事件等。 Abp.Events…

Keil编译STM32工程,提示__align(4)处语法错误

好久没有用Keil编程&#xff0c;因为别人的代码是用Keil写的&#xff0c;所以又得安装起来&#xff0c;编译时遇到__align(4)的错误提示。 这个问题主要是编译器版本的问题&#xff0c;默认使用的是v6.19版本的编译器&#xff0c;而工程原来使用的是v5版本的&#xff0c;两个编…

B039-SpringMVC基础

目录 SpringMVC简介复习servletSpringMVC入门导包配置前端控制器编写处理器实现Contoller接口普通类加注解(常用) 路径问题获取参数的方式过滤器简介自定义过滤器配置框架提供的过滤器 springMVC向页面传值的三种方式视图解析器springMVC的转发和重定向 SpringMVC简介 1.Sprin…

Windows如何安装使用TortoiseSVN客户端并实现公网访问本地SVN Server

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

接口测试和测试用例分析

只要有软件产品的公司百分之九十以上都会做接口测试&#xff0c;要做接口测试的公司那是少不了接口测试工程师的&#xff0c;接口测试工程师相对于其他的职位又比较轻松并且容易胜任。如果你想从事接口测试的工作那就少不了对接口进行分析&#xff0c;同时也会对测试用例进行研…

解决 Hive 外部表分隔符问题的实用指南

简介&#xff1a; 在使用 Hive 外部表时&#xff0c;分隔符设置不当可能导致数据导入和查询过程中的问题。本文将详细介绍如何解决在 Hive 外部表中正确设置分隔符的步骤。 问题描述&#xff1a; 在使用Hive外部表时&#xff0c;可能会遇到分隔符问题。这主要是因为Hive在读…

同一个数组中对象去重

封装方法 fn1 (tempArr) {this.echartList.map(item > {for (let i 0; i < item.data.length; i) {for (let j i 1; j < item.data.length; j) {if (item.data[i].deviceId item.data[j].deviceId && item.data[i].time item.data[j].time && it…

解决win10下强制设置web浏览器为microsoft edge的方法

目录 问题场景实现方法禁止edge默认选项设置默认浏览器 反思 问题场景 因为一些特殊的原因&#xff0c;我需要第二个浏览器&#xff0c;我的第一个浏览器是google的chrome浏览器&#xff0c;所以我选择的是windows的默认浏览器&#xff0c;就是microsoft edge浏览器&#xff0…

easyExcel生成excel并导出自定义样式------添加复杂表头

easyExcel生成excel并导出自定义样式------添加复杂表头 设置合并竖行单元格&#xff0c;表头设置 OutputStream outputStream ExcelUtils.getResponseOutputStream(response, fileName);//根据数据组装需要合并的单元格Map<String, List<String>> strategyMap …

React学习计划-React16--React基础(二)组件与组件的3大核心属性state、props、ref和事件处理

1. 组件 函数式组件&#xff08;适用于【简单组件】的定义&#xff09; 示例&#xff1a; 执行了ReactDOM.render(<MyComponent/>, ...)之后执行了什么&#xff1f; React解析组件标签&#xff0c;找到了MyComponent组件发现组件是使用函数定义的&#xff0c;随后调用该…