首页
首页 教程 派聪明
  • 首页
  • 教程
  • 派聪明
  • 登录
登录技术派畅享更多权益

用户名密码登录

其他登录:
icon_GitHubCreated with sketchtool.
绑定星球,畅享VIP服务

微信扫码/长按识别登录

输入验证码
有效期五分钟 👉 手动刷新

登录即同意 用户协议 和 隐私政策

绑定二哥编程星球,畅享 VIP 尊享服务!

戳我了解如何获取星球编号,新窗口打开

添加二哥微信 itwanger 审核更快

记得备注 星球编号
我会根据星球编号进行审核
1
两数之和
更新时间: 2023年12月09日
星球
2
两数相加
更新时间: 2023年12月10日
星球
3
无重复字符的最长子串
更新时间: 2023年12月12日
星球
4
寻找两个正序数组的中位数
更新时间: 2023年12月14日
星球
5
最长回文子串
更新时间: 2023年12月18日
星球
6
Z 字行变换
更新时间: 2023年12月26日
星球
7
整数反转
更新时间: 2023年12月28日
星球
8
字符串转成整数
更新时间: 2024年01月01日
星球
9
回文数
更新时间: 2024年01月03日
星球
10
正则式匹配
更新时间: 2024年01月17日
星球
11
盛最多水的容器
更新时间: 2024年01月20日
星球
12
整数转罗马数字
更新时间: 2024年01月21日
星球
13
罗马数字转整数
更新时间: 2024年01月22日
星球
14
最长公共前缀
更新时间: 2024年01月23日
星球
15
三数之和
更新时间: 2024年01月25日
星球
16
最接近的三数之和
更新时间: 2024年01月27日
星球
17
电话号码的字母组合
更新时间: 2024年01月29日
星球
18
四数之和
更新时间: 2024年01月30日
星球
19
删除链表中的倒数第N个节点
更新时间: 2024年01月31日
星球
20
有效的括号
更新时间: 2024年02月01日
星球
21
合并两个有序链表
更新时间: 2024年02月02日
星球
22
括号生成
更新时间: 2024年02月03日
星球
23
合并K个升序链表
更新时间: 2024年02月04日
星球
24
两两交换链表中的节点
更新时间: 2024年02月06日
星球
25
K个一组翻转链表
更新时间: 2024年02月07日
星球
26
删除有序数组中的重复项
更新时间: 2024年02月11日
星球
27
移除元素
更新时间: 2024年02月14日
星球
28
实现 strStr()
更新时间: 2024年02月19日
星球
29
两数相除
更新时间: 2024年02月22日
星球
30
串联所有单词的子串
更新时间: 2024年02月27日
星球
31
下一个排列
更新时间: 2024年02月29日
星球
32
最长有效括号
更新时间: 2024年05月30日
星球
33
搜索旋转排序数组
更新时间: 2024年06月03日
星球
34
在排序数组中查找元素的头尾位置
更新时间: 2024年06月14日
星球
35
搜索插入位置
更新时间: 2024年06月15日
星球
36
有效的数独
更新时间: 2024年06月16日
星球
37
解数独
更新时间: 2024年08月01日
星球
38
外观数列
更新时间: 2024年08月02日
星球
39
组合总和
更新时间: 2024年08月03日
星球
40
组合总和②
更新时间: 2024年08月04日
星球
41
缺失的第一个整数
更新时间: 2024年08月06日
星球
42
接雨水
更新时间: 2024年08月07日
星球
43
字符串相乘
更新时间: 2024年08月08日
星球
44
通配符匹配
更新时间: 2024年09月04日
星球
45
跳跃游戏
更新时间: 2024年09月06日
星球
46
全排列
更新时间: 2024年09月08日
星球
47
全排列②
更新时间: 2024年09月14日
星球
48
旋转图像
更新时间: 2024年09月18日
星球
49
字母异位词分组
更新时间: 2024年09月20日
星球
50
Pow(x, n)
更新时间: 2024年09月29日
星球
51
N 皇后
更新时间: 2024年11月14日
星球
52
N 皇后②
更新时间: 2024年11月14日
星球
53
最大子数组和
更新时间: 2024年11月16日
星球
54
螺旋矩阵
更新时间: 2024年11月20日
星球
55
跳跃游戏
更新时间: 2024年11月21日
星球
56
合并区间
更新时间: 2025年01月26日
星球
57
插入区间
更新时间: 2025年02月01日
星球
关注公众号
原创
二哥的 LeetCode 刷题笔记:003.无重复字符的最长子串

《二哥的 LeetCode 刷题笔记》真的经典。 ------------------------by鲁迅

题意

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

示例

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

难度

中等

分析1

看完这道题目的描述,脑袋里面要先搞清楚几个概念:

  • 什么是子串?
  • 什么是最长子串?
  • 什么是不含重复字符的最长子串?

这三个概念搞清楚,才能去写题解,对吧?

什么是子串?拿题目给出的示例来说,abcabcbb,它的子串有:

a、b、c、a、b、c、b、b 这种单个子串
ab、bc、ca、cb、bb 这种两个字符组成的子串
abc、bca、cab、bcb、cbb 这种三个字符组成的子串
abca、bcab、cabc、abcb 这种四个字符组成的子串
abcab、bcabc、cabcb、abcbb 这种五个字符组成的子串
abcabc、bcabcb、cabcbb 这种六个字符组成的子串
abcabcb bcabcbb 这种七个字符组成的子串
abcabcbb 这种八个字符组成的子串

什么是最长子串?

就是子串中字符个数最多的那个子串,比如上面的例子中,abcabcbb就是最长子串。

什么是不含重复字符的最长子串?

就是最长子串中没有重复字符的那个子串,abcabcbb 虽然是最长子串,但有重复字符 a、b、c,所以不是不含重复字符的最长子串。

abcabcb 也不是,因为有重复字符 a、b、c。

abcabc 也不是,因为有重复字符 a、b、c。

abcab 也不是,因为有重复字符 a、b。

abca 也不是,因为有重复字符 a。

排除到最后,你会发现,不含重复字符的最长子串有这么几个:

abc、bca、cab

OK,答案出来了,长度为 3。

借着这个思路,我们直接来暴力解题。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int res = 0; // 用于存储最长子串的长度
        // 外层循环,从字符串的第一个字符开始
        for (int i = 0; i < s.length(); i++) {
            boolean[] book = new boolean[300]; // 布尔数组,用于标记字符是否出现过

            // 内层循环,从当前字符向前遍历
            for (int j = i; j >= 0; j--) {
                // 如果字符已经在子串中出现过,结束内层循环
                if (book[s.charAt(j)]) 
                    break;

                // 标记当前字符为出现过
                book[s.charAt(j)] = true;
                // 更新最长子串的长度
                res = Math.max(res, i - j + 1);
            }
        }
        return res; // 返回最长子串的长度
    }
}

两层循环,第一层循环用来确定起始位置,第二层循环用来确定结束位置,向前去找最长的子串,如果字符出现过,我们就标记它为 true,并且计算最长子串的长度。

①、题目说 s 由英文字母、数字、符号和空格组成,那么它很可能是 ASCII 码字符集,在 ASCII 字符集中,有 128 个不同的字符,这包括了大小写英文字母(52个)、数字(10个)、标点符号和特殊字符(如空格、制表符等),以及一些控制字符。

那为了节省空间,数组 book 的长度其实可以声明为 128,而不是 300。

boolean[] book = new boolean[128]; // 足以覆盖所有 ASCII 字符

当然了,笔试的时候时间紧张,如果没办法考虑周全的话,300 肯定是一个保险的方案,确保出现的字符都能够容纳得下。

②、i - j + 1 用来计算子串的长度,这里的 i 是外层循环的循环变量,j 是内层循环的循环变量,i - j + 1 就是子串的长度。

  • i 是子串末尾字符的索引。
  • j 是子串起始字符的索引。
  • i - j 是子串起始和结束字符之间的距离(即子串的长度减去 1)。
  • 加上 1 (i - j + 1) 是为了包含起始字符在内的整个子串的长度。

在例子 "abcabcbb" 中,当我们考虑以第一个 'b'(索引 1)结尾的子串时:

  • 当 i = 1('b' 的位置)和 j = 1(仍然是 'b' 的位置)时,i - j + 1 = 1,表示子串 "b" 的长度。
  • 当 i = 1 和 j = 0('a' 的位置)时,i - j + 1 = 2,表示子串 "ab" 的长度。

当字符串 s = "abcabcbb" 时,我们用该题解来模拟一下整个题解的过程。

  1. 初始化:最长子串长度 res = 0。

  2. 开始外层循环:逐字符遍历字符串 s。

    • i = 0(字符 'a'):

      • 初始化 book 数组,其中所有值均为 false。
      • 内层循环:从 j = 0 开始向前遍历。
        • 检查 'a' 是否已经出现过(book[s.charAt(0)]),结果为 false。
        • 标记 'a' 为出现过(book['a'] = true)。
        • 更新 res 为 max(res, i - j + 1),即 max(0, 0 - 0 + 1) = 1。
        • 退出内层循环。
        • 注意:这里的子串是 "a",长度为 1。
    • i = 1(字符 'b'):

      • 初始化 book 数组,其中所有值均为 false。
      • 内层循环:从 j = 1 开始向前遍历。
        • 检查 'b' 是否已经出现过,结果为 false。
        • 标记 'b' 为出现过。
        • 更新 res 为 max(1, 1 - 1 + 1) = 1。
      • 内层循环:j = 0。
        • 检查 'a' 是否已经出现过,结果为 false。
        • 标记 'a' 为出现过。
        • 更新 res 为 max(1, 1 - 0 + 1) = 2。
        • 退出内层循环。
        • 注意:这里的子串是 "ab",长度为 2。
    • i = 2(字符 'c'):

      • 初始化 book 数组,其中所有值均为 false。
      • 内层循环:从 j = 2 开始向前遍历。
        • 检查 'c' 是否已经出现过,结果为 false。
        • 标记 'c' 为出现过。
        • 更新 res 为 max(1, 2 - 2 + 1) = 1。
      • 内层循环:j = 1
        • 检查 'b' 是否已经出现过,结果为 false。
        • 标记 'b' 为出现过。
        • 更新 res 为 max(1, 2 - 1 + 1) = 2。
      • 内层循环:j = 0
        • 检查 'a' 是否已经出现过,结果为 false。
        • 标记 'a' 为出现过。
        • 更新 res 为 max(2, 2 - 0 + 1) = 3。
        • 退出内层循环。
        • 注意:这里的子串是 "abc",长度

已加入二哥编程星球,即刻绑定星球编号解锁🔐

该文档仅「二哥编程星球」的VIP用户可见

二哥的编程星球内容包括:

1. 付费文档: 技术派、MYDB 等项目配套的 120+篇教程查看权限

2. 面试指南: 校招、社招的 40 万+字面试求职攻略

3. 智能助手: 无限期使用派聪明 AI 助手,已对接讯飞星火和 ChatGPT双通道,不用花 1 分钱

4. 专属问答: 向二哥 1v1 发起提问,内容不限于 offer 选择、学习路线、职业规划等

5. 简历修改: 提供简历修改服务,附赠星球 100+优质简历模板可供参考

6. 学习环境: 打造一个沉浸式的学习环境,有一种高考冲刺、大学考研的氛围


二哥的星球

》步骤①:微信扫描上方二维码,点击「加入知识星球」按钮

》步骤②:访问星球置顶帖球友必看: https://t.zsxq.com/11rEo9Pdu,获取项目配套文档的语雀访问地址和密码

已加入星球,绑定星球编号
删除提醒

确定删除《二哥的 LeetCode 刷题笔记:003.无重复字符的最长子串》吗

4人已点赞

回复