LeetCode 第3题:无重复字符的最长子串

题目描述

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

难度

中等

题目链接

https://leetcode.cn/problems/longest-substring-without-repeating-characters/

示例

示例 1:

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

示例 2:

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

示例 3:

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

提示

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

解题思路

方法一:滑动窗口

这道题可以使用滑动窗口的方法解决。滑动窗口是一种在数组或字符串上使用双指针的技巧,通过移动左右指针形成一个窗口,在窗口内进行操作。

关键点:

  1. 使用两个指针(left和right)维护一个滑动窗口
  2. 使用HashSet记录窗口内的字符,保证无重复
  3. 当遇到重复字符时,移动左指针直到删除重复字符
  4. 在移动过程中更新最大长度

具体步骤:

  1. 初始化左指针left = 0,右指针right = 0
  2. 创建HashSet存储窗口内的字符
  3. 移动右指针,将字符加入Set:
    • 如果字符不在Set中,加入Set并更新最大长度
    • 如果字符在Set中,移动左指针并删除字符,直到没有重复
  4. 重复步骤3直到右指针到达字符串末尾

时间复杂度:O(n),其中n是字符串长度

空间复杂度:O(min(m,n)),其中m是字符集大小

方法二:优化的滑动窗口

使用Dictionary/HashMap代替HashSet,存储字符最后出现的位置,可以直接跳转左指针位置,避免一个个删除字符。

代码实现

C# 实现(基本滑动窗口)

public class Solution {
public int LengthOfLongestSubstring(string s) {
// 特殊情况处理
if (string.IsNullOrEmpty(s)) return 0; // 创建HashSet存储当前窗口中的字符
HashSet<char> window = new HashSet<char>();
int maxLength = 0;
int left = 0; // 右指针遍历字符串
for (int right = 0; right < s.Length; right++) {
// 如果发现重复字符,移动左指针直到删除重复字符
while (window.Contains(s[right])) {
window.Remove(s[left]);
left++;
} // 将当前字符加入窗口
window.Add(s[right]); // 更新最大长度
maxLength = Math.Max(maxLength, right - left + 1);
} return maxLength;
}
}

C# 实现(优化的滑动窗口)

public class Solution {
public int LengthOfLongestSubstring(string s) {
// 特殊情况处理
if (string.IsNullOrEmpty(s)) return 0; // 创建Dictionary存储字符最后出现的位置
Dictionary<char, int> lastPos = new Dictionary<char, int>();
int maxLength = 0;
int left = 0; // 右指针遍历字符串
for (int right = 0; right < s.Length; right++) {
char currentChar = s[right]; // 如果字符已存在,直接将左指针移动到重复字符的下一位
if (lastPos.ContainsKey(currentChar)) {
left = Math.Max(left, lastPos[currentChar] + 1);
} // 更新字符最后出现的位置
lastPos[currentChar] = right; // 更新最大长度
maxLength = Math.Max(maxLength, right - left + 1);
} return maxLength;
}
}

代码详解

基本滑动窗口版本:

  1. HashSet<char> window:用于存储当前窗口中的字符,保证无重复
  2. while (window.Contains(s[right])):当发现重复字符时,不断移动左指针并删除字符
  3. maxLength = Math.Max(maxLength, right - left + 1):更新最大长度

优化版本:

  1. Dictionary<char, int> lastPos:存储每个字符最后出现的位置
  2. left = Math.Max(left, lastPos[currentChar] + 1)
    • 当发现重复字符时,直接将左指针移动到重复字符上次出现位置的下一位
    • 使用Math.Max是为了防止左指针回退

执行结果

基本滑动窗口版本:

  • 执行用时:84 ms
  • 内存消耗:39.5 MB

优化版本:

  • 执行用时:72 ms
  • 内存消耗:39.8 MB

总结与反思

  1. 这是一道经典的滑动窗口题目,考察了:

    • 滑动窗口的基本应用
    • 字符串的处理
    • 哈希表的使用
  2. 两种实现方式各有优势:
    • 基本版本思路更直观,易于理解
    • 优化版本性能更好,避免了多次移动左指针
  3. 关键点:
    • 理解子串和子序列的区别
    • 正确维护滑动窗口
    • 高效处理重复字符

相关题目

  • LeetCode 第159题:至多包含两个不同字符的最长子串
  • LeetCode 第340题:至多包含 K 个不同字符的最长子串
  • LeetCode 第395题:至少有 K 个重复字符的最长子串
  • LeetCode 第424题:替换后的最长重复字符

LeetCode 第3题:无重复字符的最长子串的更多相关文章

  1. LeetCode 第三题--无重复字符的最长子串

    1. 题目 2.题目分析与思路 3.思路 1. 题目 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3 ...

  2. Leetcode(3)无重复字符的最长子串

    Leetcode(3)无重复字符的最长子串 [题目表述]: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 第一种方法:暴力 执行用时:996 ms: 内存消耗:12.9MB 效果: ...

  3. LeetCode刷题--无重复字符的最长子串(中等)

    题目描述: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 " ...

  4. 【LeetCode题解】3_无重复字符的最长子串(Longest-Substring-Without-Repeating-Characters)

    目录 描述 解法一:暴力枚举法(Time Limit Exceeded) 思路 Java 实现 Python 实现 复杂度分析 解法二:滑动窗口(双指针) 思路 Java 实现 Python 实现 复 ...

  5. leetcode题解#3:无重复字符的最长子串

    leetcode题解:无重复字符的最长子串 题目 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: s = "abcabcbb"输出: 3 解释 ...

  6. Leetcode(3)-无重复字符的最长子串

    给定一个字符串,找出不含有重复字符的最长子串的长度. 示例: 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3. 给定 &q ...

  7. LeetCode 第 3 题:无重复字符的最长子串(滑动窗口)

    LeetCode 第 3 题:无重复字符的最长子串 (滑动窗口) 方法:滑动窗口 滑动窗口模板问题:右指针先走,满足了一定条件以后,左指针向前走,直到不满足条件. 特点:左右指针的方向是一致的,并且是 ...

  8. leetcode刷题第三天<无重复字符的最长子串>

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 : 输入: "abcabcbb" 输出: 解释: 因为无重复字符的最长子串是 . 示例 : 输入: &quo ...

  9. leetcode刷题笔记-3. 无重复字符的最长子串(java实现)

    题目描述 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "ab ...

  10. LeetCode随缘刷题之无重复字符的最长子串

    欢迎评论区交流. package leetcode.day_12_04; /** * 给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度. * <p> * 示例1: * &l ...

随机推荐

  1. select2的搜索框不能输入内容

    select2的搜索框不能输入内容 原因:原来是模态对话框强制使自己处于焦点状态,导致select2的搜索框无法获取焦点所致. 解决办法:在初始化中重写模态对话框的enforceFocus函数 $.f ...

  2. 使用缓存构建更快的 Web 应用程序

    使用 Java 缓存系统缓存频繁查看的数据 使用 Java 技术的 Web 开发人员可以使用缓存实用程序快速提升他们的应用程序的性能.Java 缓存系统(Java Caching System,JCS ...

  3. Java并发显式锁和显式条件队列

    一 显式锁 在类中利用synchronized修饰的方法或者this代码块,均使用的是类的实例锁或者类的锁.这些锁都称为内置锁. 可以利用显式锁进行协调对象的访问.即ReentrantLock.这是一 ...

  4. CVE-2023-32233 Linux 内核 UAF 漏洞分析与利用

    Linux 内核 nftable 模块在处理匿名 set 时存在 UAF. ‍ 漏洞分析 漏洞成因是 nf_tables_deactivate_set​ 在释放匿名 set 时没有将 set 的标记设 ...

  5. 关于 Span 的一切:探索新的 .NET 明星: 4. Span<T> 和 Memory<T> 是如何与 .NET 库集成的?

    4. Span<T> 和 Memory<T> 是如何与 .NET 库集成的? 1. Span<T> 是什么? 2. Span<T> 是如何实现的? 3. ...

  6. 【MyBatis】学习笔记15:通过分步查询解决一对多或多对多问题

    目录 对象 SmbmsProvider.java SmbmsBill.java 接口 providerMapper.java orderMapper.java 映射文件 providerMapper. ...

  7. docker-compose network名称定义

    docker-compose启动的网络名称: 1.没有自定义网络名 $ cat docker-compose.yaml version: '2' services: zookeeper1: image ...

  8. SpringBoot:通过多个Context限制Bean的活动范围

    从Spring的包扫描说起 SpringBoot会扫描SpringBootApplication注解标注的类,他所在的包以及这个包的子包,把那里面的Bean注册到applicationContext中 ...

  9. Qt/C++原创项目作品精选(祖传原创/性能凶残/界面精美)

    00 前言说明 从事Qt开发十年有余,一开始是做C#.NET开发的,因为项目需要,转行做嵌入式linux开发,在嵌入式linux上做可视化界面开发一般首选Qt,当然现在可选的方案很多比如安卓,但是十多 ...

  10. Qt音视频开发08-ffmpeg内核优化(极速打开/超时回调/实时响应)

    一.前言 最初编写这套视频解析组件的时候,面对的场景是视频监控行业,对应设备都是网络监控摄像机,传过来的都是rtsp这种视频流,做过这一块的人都知道,打开某个视频流默认耗时比较大,基本上在2s左右,那 ...