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

文章目录

一、题目描述

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

示例:

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

二、问题分析

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

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

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

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


三、解法一:暴力枚举法

思路

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

流程图(暴力枚举)

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

时间复杂度分析

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

不适合大数据量。


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

思路说明

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

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

动态示意图

假设输入 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) ✅ 推荐
相关推荐
Gorway3 小时前
解析残差网络 (ResNet)
算法
拖拉斯旋风3 小时前
LeetCode 经典算法题解析:优先队列与广度优先搜索的巧妙应用
算法
Wect3 小时前
LeetCode 207. 课程表:两种解法(BFS+DFS)详细解析
前端·算法·typescript
灵感__idea17 小时前
Hello 算法:众里寻她千“百度”
前端·javascript·算法
Wect1 天前
LeetCode 130. 被围绕的区域:两种解法详解(BFS/DFS)
前端·算法·typescript
NAGNIP2 天前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
颜酱2 天前
单调栈:从模板到实战
javascript·后端·算法
CoovallyAIHub2 天前
仿生学突破:SILD模型如何让无人机在电力线迷宫中发现“隐形威胁”
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
从春晚机器人到零样本革命:YOLO26-Pose姿态估计实战指南
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
Le-DETR:省80%预训练数据,这个实时检测Transformer刷新SOTA|Georgia Tech & 北交大
深度学习·算法·计算机视觉