LeetCode Hot100(7/100)—— 3. 无重复字符的最长子串

文章目录

一、题目描述

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

示例:

复制代码
输入: s = "abcabcbb"
输出: 3
解释: 最长子串是 "abc",长度为 3。

二、问题分析

这道题要求找出 最长的无重复字符的连续子串 。

可以想到用 暴力枚举法 或 滑动窗口法:

  • 暴力:枚举所有子串 → 检查是否重复 → 找最长长度。
  • 滑动窗口:用双指针维护一段不重复的区间 → 动态右扩,必要时左缩。

显然,滑动窗口是最优解法,因为它避免了重复检查。


三、解法一:暴力枚举法

思路

  • 枚举所有可能的子串起点和终点。
  • 判断该子串中是否有重复字符。
  • 记录最长长度。

流程图(暴力枚举)

无重复
有重复
开始
初始化 maxLen = 0
遍历左指针 i from 0..n-1
遍历右指针 j from i..n-1
获取 si..j
判断是否有重复字符
更新 maxLen
继续遍历
结束
返回 maxLen

时间复杂度分析

  • 时间复杂度: O(n³) (枚举所有子串 + 检查重复)
  • 空间复杂度: O(n)

不适合大数据量。


四、解法二:滑动窗口(推荐)

思路说明

滑动窗口法通过维护一段 无重复的子串区域 来动态更新结果:

  • 使用两个指针 left 和 right 表示窗口边界。
  • 使用一个 HashSet 或 HashMap 记录窗口中字符出现位置。
  • 每次右指针向右移动:
    • 若新字符不存在于窗口,则加入并更新长度。
    • 若新字符已出现,则左指针右移到出现位置之后。

动态示意图

假设输入 s = "abcabcbb"

步骤 右指针字符 当前窗口 最大长度
1 a a 1
2 b ab 2
3 c abc 3
4 a bca 3
5 b cab 3
6 c abc 3

最终结果为 3。

流程图(滑动窗口)

渲染错误: Mermaid 渲染失败: Parse error on line 5: ...|重复| E更新 left = max(left, map\[char + 1 -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'


五、复杂度分析

项目 时间复杂度 空间复杂度
暴力枚举 O(n³) O(n)
滑动窗口 O(n) O(k),其中 k 为字符集大小

滑动窗口显然更优。


六、Java 实现代码(滑动窗口)

java 复制代码
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int left = 0, maxLen = 0;
        Map<Character, Integer> map = new HashMap<>();

        for (int right = 0; right < n; right++) {
            char c = s.charAt(right);
            if (map.containsKey(c)) {
                // 更新左指针到重复字符之后位置
                left = Math.max(left, map.get(c) + 1);
            }
            map.put(c, right);
            maxLen = Math.max(maxLen, right - left + 1);
        }
        return maxLen;
    }
}

七、补充:使用数组优化

若字符集已知(如仅英文字符),可用数组代替 Map:

java 复制代码
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int[] index = new int[128]; // ASCII
        int left = 0, maxLen = 0;
        for (int right = 0; right < s.length(); right++) {
            char c = s.charAt(right);
            left = Math.max(index[c], left);
            maxLen = Math.max(maxLen, right - left + 1);
            index[c] = right + 1;
        }
        return maxLen;
    }
}

总结

方法 核心思路 时间复杂度 是否推荐
暴力法 枚举所有子串 + 检查重复 O(n³) 否
滑动窗口 + HashMap 动态维护无重复窗口 O(n) ✅ 推荐
滑动窗口 + 数组优化 改进存储结构 O(n) ✅ 推荐
相关推荐
飘尘5 小时前
从"算子"到"AI Infra":大模型背后看不见的那群人在忙什么
人工智能·算法·面试
夏幻灵6 小时前
每日一题:LeetCode 3:无重复字符的最长子串——滑动窗口思路详解
算法·leetcode·职场和发展
CarIise6 小时前
Java实训阶段查漏补缺复习笔记2
java·linux·算法
无忧.芙桃7 小时前
C++ 并查集详解:原理、实现与应用
c语言·c++·算法·leetcode
蛋蛋的就会顺顺的7 小时前
hot100——二叉树
java·数据结构·算法·leetcode·力扣
Code_Solitude7 小时前
c语言:二分法的完整补充
c语言·开发语言·算法
一切皆是因缘际会7 小时前
掌控信息论:同源星际通信基础理论
人工智能·算法·ai
动词ing9 小时前
【C语言题目练习】算法 整数反转
c语言·开发语言·算法
Nil20810 小时前
leetcode 55跳跃游戏
算法·leetcode·游戏
longlongzihan10 小时前
LeetCode 128. 最长连续序列 —— 从排序到哈希集合
数据结构·c++·算法·leetcode·排序算法·哈希表