LeetCode刷题之HOT100之无重复字符的最长子串

今天搬工位了,研二的师兄师姐在这儿坐了半年,现在轮到我么们了。做题先

1、题目描述

在这里插入图片描述

2、逻辑分析

题目要求很明确,就是要找出无重复字符的最长。怎么求解呢?题解给出了滑动窗口的算法方案。

在这里插入图片描述
在这里插入图片描述

3、代码演示

public int lengthOfLongestSubstring(String s) {
        // 创建一个HashSet来存储已经出现过的字符,以便快速检查某个字符是否已经出现过 
        Set<Character> occ = new HashSet<Character>();
        // 获取字符串的长度
        int n = s.length();
        // 初始化右指针rk为-1,表示还未开始寻找子串 
        // ans存储最长子串的长度,初始化为0  
        int rk = -1 , ans = 0;
        // 遍历字符串的每一个字符  
        for(int i = 0; i < n; i++){
            // 如果i不是第一个字符(即i不等于0),则从HashSet中移除前一个字符,因为当前子串的起始位置已经后移了
            if(i != 0){
                occ.remove(s.charAt(i - 1));
            }
            // 使用while循环来扩展当前子串,直到遇到已经出现过的字符或者到达字符串的末尾
            // 如果当前字符不在HashSet中,说明可以添加到子串中,并且更新rk
            while(rk + 1 < n && !occ.contains(s.charAt(rk + 1))){
                occ.add(s.charAt(rk + 1));
                rk++;
            }
            // 更新最长子串的长度,取当前子串长度(rk - i + 1)和之前记录的最长子串长度ans的较大值
            ans = Math.max(ans , rk - i + 1);
        }
        // 返回最长子串的长度
        return ans;
    }

这段代码使用双指针(一个左指针i和一个右指针rk)和一个HashSet来解决问题。左指针 i 用于遍历字符串的每个字符,右指针 rk 用于扩展当前子串。每次移动左指针时,都会从HashSet中移除前一个字符,以确保当前子串不包含重复字符。然后,使用while循环来扩展当前子串,直到遇到重复字符或到达字符串的末尾。最后,更新最长子串的长度并返回。

我们可以使用字符串 “abcabcbb” 作为例子来详细解释上述代码的执行过程。字符串: “abcabcbb”

初始状态: occ (HashSet): 空集,n (字符串长度): 7,rk (右指针): -1,ans (最长子串长度): 0,i (左指针): 即将开始遍历。

步骤 1

(i = 0, rk = -1, ans = 0): occ.remove(s.charAt(i - 1)): 不执行(因为 i = 0)
while 循环: 将 ‘a’ 添加到 occ,rk 增加到 0
更新 ans: ans = Math.max(ans, rk - i + 1) = Math.max(0, 1) = 1

步骤 2

(i = 1, rk = 0, ans = 1): occ.remove(s.charAt(i - 1)): 移除 ‘a’
while 循环: 将 ‘b’ 添加到 occ, rk 增加到 1
更新 ans: ans = Math.max(ans, rk - i + 1) = Math.max(1, 2) = 2

步骤 3

(i = 2, rk = 1, ans = 2): occ.remove(s.charAt(i - 1)): 移除 ‘b’
while 循环: 将 ‘c’ 添加到 occ, rk 增加到 2
更新 ans: ans = Math.max(ans, rk - i + 1) = Math.max(2, 3) = 3

步骤 4

(i = 3, rk = 2, ans = 3): occ.remove(s.charAt(i - 1)): 移除 ‘c’
while 循环: !occ.contains(s.charAt(rk + 1)): 否(因为 ‘a’ 已经在 occ 中)
不执行添加和增加 rk
更新 ans: 保持为 3

步骤 5

(i = 4, rk = 2, ans = 3): occ.remove(s.charAt(i - 1)): 移除 ‘a’(这是之前 rk 指向的字符)
while 循环: rk + 1 < n: 是(因为 rk = 2), !occ.contains(s.charAt(rk + 1)): 是(因为 ‘b’ 不在 occ 中)
将 ‘b’ 添加到 occ , rk 增加到 3
更新 ans: ans = Math.max(ans, rk - i + 1) = Math.max(3, 2) = 3(长度没有增加)

接下来的步骤(i = 6,7,8)会按照类似的逻辑继续执行,但 ans 不会再增加,因为最长的无重复字符子串长度已经确定为 3。

滑动窗口思想需要好好消化,今天没睡好,晚上状态不好啊,睡眠太重要了,再见,朋友们!

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值