Skip to content

算法:无重复字符的最长子串

轩辕十四
Published date:

Table of contents

Open Table of contents

题目

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

解法

func lengthOfLongestSubstring(_ s: String) -> Int {
  var maxLength = 0
  var left = 0
  var dict = [Character: Int]()
  for (i, char) in s.enumerated() {
    if let index = dict[char] {
      left = max(left, index + 1)
    }
    dict [char] = i
    maxLength = max(maxLength, i - left + 1)
  }

  return maxLength
}

解题思路

  1. 滑动窗口的思想

我们使用滑动窗口方法维护一个当前不含重复字符的子串。通过两个指针(这里用变量 left 表示窗口左边界,i 表示当前字符的索引),不断更新窗口的范围。

  1. 使用哈希字典记录字符位置

定义一个字典 dict 用来存储每个字符最后一次出现的位置。这样,当遇到重复字符时,就可以根据该字符上一次出现的位置,决定如何移动窗口左边界。

  1. 更新窗口边界

对于每个遍历到的字符 char

  1. 计算最长子串长度

每次移动窗口后,通过 i - left + 1 计算当前窗口的长度,并与当前记录的最大长度进行比较,更新最大值。

  1. 时间复杂度与空间复杂度

由于我们只需遍历一次字符串,并在遍历过程中通过哈希表进行常数时间的查找操作,因此算法的时间复杂度为 O(n),空间复杂度为 O(n)(最坏情况下哈希表中存储所有不同的字符)。

这种方法巧妙地利用滑动窗口和哈希表,能够在一次遍历中完成题目的要求,既保证了算法的效率,又使得代码逻辑清晰易懂。

Previous
算法:回文数
Next
算法:两数相加