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 是字符集的大小。这是因为哈希集合的大小取决于字符串中不同字符的数量,这个数量最大不会超过字符集的大小,同时也不会超过字符串的长度。

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

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

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

相关推荐
_日拱一卒4 分钟前
LeetCode:最长连续序列
算法·leetcode·职场和发展
2401_879503417 分钟前
C++与FPGA协同设计
开发语言·c++·算法
重生之后端学习18 分钟前
287. 寻找重复数
数据结构·算法·leetcode·深度优先·图论
抓个马尾女孩22 分钟前
位置编码:绝对位置编码、相对位置编码、旋转位置编码
人工智能·深度学习·算法·transformer
今儿敲了吗44 分钟前
46| FBI树
数据结构·c++·笔记·学习·算法
小辉同志1 小时前
139. 单词拆分
算法·动态规划
oem1101 小时前
C++中的访问者模式变体
开发语言·c++·算法
IronMurphy1 小时前
【算法二十七】230. 二叉搜索树中第 K 小的元素 199. 二叉树的右视图
算法·深度优先
暮冬-  Gentle°1 小时前
C++中的工厂方法模式
开发语言·c++·算法
番茄去哪了1 小时前
Java基础面试题day03
面试·职场和发展