【LeetCode】3. 无重复字符的最长子串

【LeetCode】3. 无重复字符的最长子串

题目

【LeetCode】3. 无重复字符的最长子串

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

示例 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. 使用左右两个指针表示当前窗口的边界
  2. 右指针不断向右移动,将字符加入哈希集合
  3. 当遇到重复字符时,移动左指针并从集合中移除相应字符,直到窗口中没有重复字符
  4. 每次移动后计算当前窗口长度,并更新最大长度

这种方法只需一次遍历,时间复杂度为O(n),非常高效。

代码实现

java 复制代码
import java.util.HashSet;
import java.util.Set;

public class LongestSubstring {
    public int lengthOfLongestSubstring(String s) {
        // 哈希集合,用于存储当前窗口中的字符
        Set<Character> set = new HashSet<>();
        int n = s.length();
        // 右指针,初始值为 -1,相当于在字符串的左边界的左侧,还没有开始移动
        int right = -1;
        int maxLength = 0;
        
        for (int left = 0; left < n; left++) {
            if (left != 0) {
                // 左指针向右移动一格,移除一个字符
                set.remove(s.charAt(left - 1));
            }
            
            // 不断移动右指针,直到遇到重复字符
            while (right + 1 < n && !set.contains(s.charAt(right + 1))) {
                set.add(s.charAt(right + 1));
                right++;
            }
            
            // 更新最大长度
            maxLength = Math.max(maxLength, right - left + 1);
        }
        
        return maxLength;
    }

    // 测试示例
    public static void main(String[] args) {
        LongestSubstring solution = new LongestSubstring();
        System.out.println(solution.lengthOfLongestSubstring("abcabcbb"));  // 输出:3
        System.out.println(solution.lengthOfLongestSubstring("bbbbb"));     // 输出:1
        System.out.println(solution.lengthOfLongestSubstring("pwwkew"));    // 输出:3
        System.out.println(solution.lengthOfLongestSubstring(""));          // 输出:0
    }
}
    

复杂度分析

  • 时间复杂度:O(n),其中n是字符串的长度。左指针和右指针分别最多移动n次。
  • 空间复杂度:O(min(m, n)),其中m是字符集的大小。在最坏情况下,整个字符串都没有重复字符,此时集合的大小为n。

关键要点

  • 滑动窗口技术的应用:通过调整左右指针维护一个有效的窗口
  • 哈希集合的使用:快速判断字符是否已存在于当前窗口中
  • 一次遍历即可完成计算,效率高,适合处理大规模字符串(题目中提示长度可达5×10^4)
  • 边界处理:当字符串为空时,直接返回0
相关推荐
IT_陈寒36 分钟前
Redis内存爆了,原来我漏掉了这个致命配置
前端·人工智能·后端
小bo波1 小时前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
fliter1 小时前
最后一块拼图:用 bitvec 构造 IPv4 包,真正做出自己的 Ping
后端
fliter2 小时前
用 Rust 解析并生成 ICMP 包:checksum、nom 与 cookie-factory
后端
蝎子莱莱爱打怪2 小时前
XZLL-IM干货系列 03|消息 ID 设计:一个 UUID 搞不定的事,我用两个 ID 解决了
后端·面试·开源
fliter2 小时前
从 panic 到 Result:用 Rust 重新整理一个 ping 项目的错误处理
后端
森蓝情丶3 小时前
我给 AI 搭了个法庭:一个前端仔的 LangGraph 实战全记录
前端·后端
JensCS猿3 小时前
从 Spring Boot 回看 SSM 框架:手动挡与自动挡的驾驶哲学
后端
爱勇宝3 小时前
干了近 8 年,一夜之间被裁:AI 时代,程序员最该害怕的不是 AI
前端·后端·程序员
科米米3 小时前
嵌入式日志模块
后端