LeetCode刷题:无重复字符的最长子串 详解 【3/1000 第三题】

news2024/11/28 18:41:09

👤作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅

LeetCode解锁1000题: 打怪升级之旅https://blog.csdn.net/cciehl/category_12625714.html
python数据分析可视化:企业实战案例https://blog.csdn.net/cciehl/category_12615648.html
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

在字符串处理问题中,力扣(LeetCode)题库中的“无重复字符的最长子串”是一个经典的问题。这个问题的目标是从给定的字符串中找到最长的不含有重复字符的子串。

问题描述

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

示例:

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

解题思路-哈希集合

算法步骤

  1. 初始化:定义两个指针,一个哈希集合,和一个用于记录最长子串长度的变量。
  2. 滑动窗口:用两个指针表示字符串中的某个子串(或窗口),随着遍历的进行,调整指针和窗口的大小。
  3. 更新哈希集合:通过哈希集合来判断字符是否重复,并据此调整左指针。
  4. 更新最长长度:每次窗口滑动时,更新不含重复字符的最长子串的长度。

时间复杂度

算法的时间复杂度为 O(n),其中 n 是字符串的长度。在最坏的情况下,每个字符将被访问两次(由两个指针各一次)。

空间复杂度

空间复杂度为O(min(m,n)),其中 m 是字符集(字母表)的大小。这是因为哈希集合的大小取决于字符串的大小 n 和字符集的大小 m。

代码示例(Python) 

def length_of_longest_substring(s: str) -> int:
    char_set = set()
    left = max_length = 0
    
    for right in range(len(s)):
        while s[right] in char_set:
            char_set.remove(s[left])
            left += 1
        char_set.add(s[right])
        max_length = max(max_length, right - left + 1)
    
    return max_length

# 测试代码
input_string = "abcabcbb"
print(length_of_longest_substring(input_string))

代码解释

  • 我们遍历输入字符串,使用两个指针 leftright 表示当前考虑的子串。
  • 我们使用一个集合 char_set 来存储当前子串中的字符。
  • 当我们碰到一个已经存在于集合中的字符时,我们就不断地移动左指针,并从集合中移除相应的字符,直到这个字符不再出现在集合中。
  • 每次我们都会更新最大长度 max_length

其他思路-字符集为数组

利用字符集为数组的方法特别适用于字符集大小固定且较小的情况,例如ASCII字符集。这种方法利用数组的索引来代表字符,数组的值来表示字符最后一次出现的位置。这样,我们可以在 O(1) 的时间内检查和更新每个字符的最后出现位置,从而在遍历字符串时快速判断当前字符是否重复,以及如何移动滑动窗口的起始位置。

代码示例

def length_of_longest_substring(s: str) -> int:
    # 初始化字符最后一次出现位置的数组,-1 表示字符尚未出现
    last_index = [-1] * 128  # ASCII 字符集大小为 128
    max_length = 0
    start = 0  # 滑动窗口的起始位置
    
    for i, char in enumerate(s):
        # 更新滑动窗口的起始位置
        # 如果当前字符之前出现过,则更新窗口起始位置为上一次出现位置 + 1
        if last_index[ord(char)] != -1:
            start = max(start, last_index[ord(char)] + 1)
        
        # 更新当前字符的最后出现位置
        last_index[ord(char)] = i
        
        # 计算当前无重复字符子串的长度,并更新最大长度
        max_length = max(max_length, i - start + 1)
    
    return max_length

# 测试代码
input_string = "abcabcbb"
print(length_of_longest_substring(input_string))

这段代码首先初始化一个长度为128的数组last_index来存储每个ASCII字符最后一次出现的索引位置,初始值为-1表示字符未出现。随后遍历字符串,使用ord(char)获取字符的ASCII值作为索引,通过last_index数组来快速查找字符最后一次出现的位置,并据此更新滑动窗口的起始位置start。最终,通过比较每个字符对应的无重复字符子串长度来得到最大值。

算法对比

  1. 时间复杂度:这个方法仍然保持 O(n) 的时间复杂度,与基于哈希集合的滑动窗口方法相同。
  2. 空间复杂度:当字符集大小固定且较小时(比如ASCII字符集),这种方法的空间复杂度实际上是 O(1),相较于哈希集合方法(在最坏情况下可能接近 O(n),尽管实际使用中较少达到这个上限)更优。
  3. 操作复杂度:使用数组直接访问和更新字符的最后一次出现位置,操作更为直接和高效,特别是在字符集较小的情况下。

因此,如果你确定字符集的大小是固定和有限的,利用字符集为数组的方法在理论上是更优的选择,尤其是在空间复杂度上。然而,这种方法的优势主要体现在处理小字符集的字符串上,例如ASCII字符集。

但是,如果问题涉及到更大的字符集,比如Unicode字符集,哈希集合的方法可能更加灵活和通用,因为它不受字符编码范围的限制。同时,哈希集合方法的代码通常更简洁、易于理解和维护,特别是对于那些对特定编码方式不太熟悉的开发者。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单片机简介(一)

51单片机 一台能够运行的计算机需要CPU做运算和控制,RAM做数据存储,ROM做程序存储,还有输入/输出设备(串行口、并行输出口等),这些被分为若干块芯片,安装在主板(印刷线路板&#xf…

文本直接生成2分钟视频,即将开源模型StreamingT2V

Picsart人工智能研究所、德克萨斯大学和SHI实验室的研究人员联合推出了StreamingT2V视频模型。通过文本就能直接生成2分钟、1分钟等不同时间,动作一致、连贯、没有卡顿的高质量视频。 虽然StreamingT2V在视频质量、多元化等还无法与Sora媲美,但在高速运…

记一次 pdfplumber 内存泄漏导致的服务器宕机

有一个项目需求,要在每天凌晨5点的时候执行一个任务,获取一系列的PDF文件并解析。 后端是Django框架,定时任务用Celery来实现的。 本地跑没什么问题,但是一放到服务器上跑就会宕机,而且是毫无征兆的宕机,…

css- 4

1.浮动 1. 浮动最初用于实现文字环绕效果 2. 现在,浮动是主流的布局方式之一 1.1元素浮动之后的特点 元素浮动之后,称为浮动元素,具有如下特点: 1. 浮动元素脱离文档流 2. 多个浮动的元素会水平排列,一行放不下自动换…

【STM32嵌入式系统设计与开发】——14PWM(pwm脉宽输入应用)

这里写目录标题 一、任务描述二、任务实施1、WWDG工程文件夹创建2、函数编辑(1)主函数编辑(2)USART1初始化函数(usart1_init())(3)USART数据发送函数( USART1_Send_Data(&#xff09…

浅聊什么是Redis?

需求:MySQL面临大量的查询,即读写操作,因此类比CPU,给数据加缓存,Redis诞生。应用程序从MySQL查询的数据,在Redis设置缓存(记录在内存中,无需IO操作),后再需要…

记录Xshell使用ed25519公钥免密链接SSH

试了半天,Xshell好像没办法导入linux生成的ssh公钥,因此需要以下步骤实现免密登录 结论,在linux公钥文件中,将客户端生成的ed25519公钥加上去即可(一个公钥单独一行) 1.使用Linux生成秘钥文件(不需要输入私钥密码passphrase)或者直接创建一…

FFmpeg 详解

FFmpeg 详解 FFmpeg 详解整体结构不同下载版本的区别常用库常用函数初始化封装格式解码器 版本对比组件注册方式对比FFmpeg 3.x 组件注册方式FFmpeg 4.x 组件注册方式 结构体比对函数对比avcodec_decode_video2()vcodec_encode_video2() 数据结构结构体分析AVFormatContextAVIn…

上位机图像处理和嵌入式模块部署(qmacvisual获取边界点)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 在图像处理中,解决了分割的问题之后,下面就是属性信息的提取。在这其中,有一种属性是非常重要的 ,那…

蓝桥杯-单片机基础12——基于2023年IIC代码实现开机次数记录(串行EEPROM存储器AT24C02)

蓝桥杯单片机组备赛指南请查看这篇文章:戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写,代码可直接在比赛开发板上使用。 型号:国信天长4T开发板(绿板),芯片:IAP15F2K6…

libusb Qt使用记录

1.libusb 下载 ,选择编译好的二进制文件,libusb-1.0.26-binaries.7z libusb Activity 2. 解压 3. 在 Qt Widgets Application 或者 Qt Console Application 工程中导入库,Qt 使用的是 minggw 64编译器,所以选择libusb-MinGW-x64。…

在岸上是永远学不会游泳的

为了让各位技术宅的师傅们了解如何追女孩,花无缺表哥来投稿啦!!! 在岸上是永远也学不会游泳的,就算是最好的教练来教你也没用,因为你没有去实践。实践是快速学习的最佳手段,将这些方法运用到工…

深度学习理论基础(三)封装数据集及手写数字识别

目录 前期准备一、制作数据集1. excel表格数据2. 代码 二、手写数字识别1. 下载数据集2. 搭建模型3. 训练网络4. 测试网络5. 保存训练模型6. 导入已经训练好的模型文件7. 完整代码 前期准备 必须使用 3 个 PyTorch 内置的实用工具(utils): ⚫…

java数据结构与算法刷题-----LeetCode695. 岛屿的最大面积

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 深度优先遍历2. 广度优先 1. 深度优先遍历 这不是找最短路径&…

量化交易入门(三十八)CCI指标Python实现和回测

今天我们先单纯用CCI指标来完成策略的编写,后续我们会改进这个策略,将CCI指标和前面讲到的MACD和RSI相结合来优化,看看我们优化后的效果会不会更好。 一、量化策略 CCI指标在量化交易中的策略: 在以下情况下生成买入信号&#…

C# 排序的多种实现方式(经典)

一、 对数组进行排序 最常见的排序是对一个数组排序,比如: int[] aArray new int[8] { 18, 17, 21, 23, 11, 31, 27, 38 }; 1、利用冒泡排序进行排序: (即每个值都和它后面的数值比较,每次拿出最小值) s…

黄仁勋:我们有望在未来五到十年内见证完全由人工智能生成的游戏

黄仁勋:我们有望在未来五到十年内见证完全由人工智能生成的游戏 近日,英伟达(Nvidia)GPU技术大会上,英伟达首席执行官黄仁勋(Jensen Huang)对未来游戏产业的展望引发了业界的广泛关注。在一次与…

centos安装docker,docker安装centos进而安装宝塔

背景 由于工作需要自己有许多的web应用要部署在云服务器上。然而资金有限每年都要去阿里云,腾讯云,华为云买最便宜的服务器,这就意味着每年都要经历一次痛苦的环境安装项目部署的过程(nginx、mysql、elasticsearch、redis等等&am…

【Redis】Redis的类型及相关操作

一、常用的key操作命令 keys * 查看当前数据库的键值 ttl key 查看还有多少秒过期,-1表示永不过期,-2表示过期 del / unlink key 同样是删除,unlink是非阻塞删除,del则有可能导致阻塞 select dbindex 切换数据库 flushdb 清空…

CA根证书——https安全保障的基石

HTTPS通信中,服务器端使用数字证书来证明自己的身份。客户端需要验证服务器发送的证书的真实性。这就需要一个可信的第三方机构,即CA,来颁发和管理证书。CA根证书是证书颁发机构层次结构的顶级证书,客户端信任的所有证书都可以追溯…