LeetCode 第三题: 无重复字符的最长子串

文章目录

  • 题目描述
  • [解题思路 - 滑动窗口法](#解题思路 - 滑动窗口法)
    • [Go语言实现 - 滑动窗口法](#Go语言实现 - 滑动窗口法)
    • 算法分析
  • [解题思路 - 优化的滑动窗口法](#解题思路 - 优化的滑动窗口法)

题目描述

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

示例

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

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是子串的长度,"pwke" 是一个子序列,不是子串。

解题思路 - 滑动窗口法

这个问题可以用"滑动窗口"技术来解决。滑动窗口是数组/字符串问题中常用的抽象概念。窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即 [i, j)(左闭右开)。在这里,我们将使用哈希集合来检查一个字符是否已经在当前的子串中。我们可以使用两个指针表示字符串中的某个子串(或窗口)的左右边界。右指针向右移动扩大窗口直到右指针到达字符串尽头;左指针向右移动以减小窗口直到窗口不再包含重复字符。在移动指针的过程中,我们记录并更新不含重复字符的最长子串的长度。

Go语言实现 - 滑动窗口法

go 复制代码
func lengthOfLongestSubstring(s string) int {
    charIndexMap := make(map[byte]int)
    maxLength := 0
    for i, j := 0, 0; j < len(s); j++ {
        if index, ok := charIndexMap[s[j]]; ok {
            i = max(i, index)
        }
        maxLength = max(maxLength, j-i+1)
        charIndexMap[s[j]] = j + 1
    }
    return maxLength
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

算法分析

  • 时间复杂度: O(n),其中 n 是字符串的长度。我们只需要遍历一次字符串即可。
  • 空间复杂度: O(min(m, n)),其中 m 是字符集的大小。这是因为哈希集合的大小取决于字符串中不同字符的数量,这个数量最大不会超过字符集的大小,同时也不会超过字符串的长度。

解题思路 - 优化的滑动窗口法

虽然上述滑动窗口法已经很高效,但在某些情况下,当窗口内的字符被移除时,我们可以跳过窗口中的一些字符,直接移动到重复字符的下一个位置,这可以通过存储字符的最新索引来实现。

这个方法与上面提到的滑动窗口法实际上是一样的。优化点主要在于如何更有效地更新左指针的位置。在实践中,由于这种情况出现的不多,所以实际的性能提升可能不大。因此,上面的实现已经足够满足大多数情况下的需求。

相关推荐
王老师青少年编程11 分钟前
信奥赛C++提高组csp-s之欧拉回路
c++·算法·csp·欧拉回路·信奥赛·csp-s·提高组
墨有66618 分钟前
数学分析栈的出栈顺序:从算法判断到数学本质(卡特兰数初探)
c++·算法·数学建模
zhutoutoutousan23 分钟前
氛围数学学习:用游戏化思维征服抽象数学
学习·算法·游戏
西伯利亚狼_J202023 分钟前
资料260107J-Go
职场和发展
guygg8837 分钟前
基于捷联惯导与多普勒计程仪组合导航的MATLAB算法实现
开发语言·算法·matlab
fengfuyao98538 分钟前
遗传算法与粒子群算法求解非线性函数最大值问题
算法
LeetCode天天刷1 小时前
【软件认证】比特翻转【滑动窗口】
算法
源代码•宸1 小时前
Leetcode—1123. 最深叶节点的最近公共祖先【中等】
经验分享·算法·leetcode·职场和发展·golang·dfs
s砚山s1 小时前
代码随想录刷题——二叉树篇(十三)
数据结构·算法
alphaTao1 小时前
LeetCode 每日一题 2026/1/5-2026/1/11
算法·leetcode