算法:无重复字符的最长子串
题目
给定一个字符串 s
,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
1 | 输入: s = "abcabcbb" |
示例 2:
1 | 输入: s = "bbbbb" |
示例 3:
1 | 输入: s = "pwwkew" |
提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
解法
1 | func lengthOfLongestSubstring(_ s: String) -> Int { |
解题思路
- 滑动窗口的思想
我们使用滑动窗口方法维护一个当前不含重复字符的子串。通过两个指针(这里用变量 left
表示窗口左边界,i
表示当前字符的索引),不断更新窗口的范围。
- 使用哈希字典记录字符位置
定义一个字典 dict
用来存储每个字符最后一次出现的位置。这样,当遇到重复字符时,就可以根据该字符上一次出现的位置,决定如何移动窗口左边界。
- 更新窗口边界
对于每个遍历到的字符 char
:
如果该字符已经存在于字典中,则说明窗口内出现了重复字符。此时更新
left
为index + 1
和当前left
的较大值,确保窗口内不包含重复字符。然后更新
dict[char]
为当前的索引i
。
- 计算最长子串长度
每次移动窗口后,通过 i - left + 1
计算当前窗口的长度,并与当前记录的最大长度进行比较,更新最大值。
- 时间复杂度与空间复杂度
由于我们只需遍历一次字符串,并在遍历过程中通过哈希表进行常数时间的查找操作,因此算法的时间复杂度为 O(n)
,空间复杂度为 O(n)
(最坏情况下哈希表中存储所有不同的字符)。
这种方法巧妙地利用滑动窗口和哈希表,能够在一次遍历中完成题目的要求,既保证了算法的效率,又使得代码逻辑清晰易懂。