返回
如何在 LeetCode 3 中找出无重复字符最长子串
见解分享
2023-12-31 08:55:15
引言
LeetCode 3:无重复字符的最长子串是 LeetCode 中一项颇受欢迎的问题,它要求我们找到给定字符串中不包含重复字符的最长子串的长度。本篇文章将详细剖析一种高效且易于理解的解决方案——滑动窗口算法。
算法概述
滑动窗口算法以一系列窗口或子串扫描整个字符串。对于每个窗口,我们都会检查其是否满足我们的条件,即没有重复的字符。然后,我们更新窗口以检查下一个子串,同时维护最长的有效子串长度。这种算法的优点在于其时间复杂度较低,并且适用于各种字符串处理问题。
算法步骤
- 初始化滑动窗口: 设置两个指针,起始指针
start
和结束指针end
,将它们都指向字符串的开头。同时,我们初始化最长子串的长度max_length
为 0。 - 扩展窗口: 使用循环增加
end
指针,使窗口向右移动。在每次移动后,我们检查窗口中是否出现了重复的字符。如果出现重复的字符,我们继续增加end
指针,直到窗口中不再有重复的字符。 - 更新最长子串长度: 当窗口中没有重复的字符时,我们更新最长子串长度
max_length
为窗口的长度。 - 收缩窗口: 如果窗口的长度大于最长子串长度,我们收缩窗口,使
start
指针向右移动,并重新开始扩展窗口的步骤。 - 循环: 重复步骤 2 到 4,直到
end
指针到达字符串的末尾。
示例
为了更好地理解滑动窗口算法的运作方式,我们以字符串 "abcabcbb" 为例。
def longest_substring_without_repeating_characters(string):
start = 0
end = 0
max_length = 0
char_set = set()
while end < len(string):
# 如果当前字符不在集合中,则将其添加到集合并扩展窗口
if string[end] not in char_set:
char_set.add(string[end])
end += 1
max_length = max(max_length, end - start)
# 如果当前字符已经在集合中,则收缩窗口并移除重复的字符
else:
char_set.remove(string[start])
start += 1
return max_length
print(longest_substring_without_repeating_characters("abcabcbb")) # 输出 3
时间复杂度与空间复杂度
滑动窗口算法的时间复杂度为 O(n),其中 n 为字符串的长度。在最坏的情况下,算法需要对每个字符进行检查,从而导致 O(n²) 的时间复杂度。然而,对于大多数字符串,算法的平均时间复杂度接近 O(n)。
空间复杂度方面,滑动窗口算法需要一个集合来存储窗口中的字符,因此空间复杂度为 O(k),其中 k 是窗口中不重复字符的最大数量。在最坏的情况下,当字符串中不包含重复字符时,空间复杂度将达到 O(n)。
结论
滑动窗口算法是解决 LeetCode 3:无重复字符的最长子串的有效方法之一。这种算法具有较低的时间复杂度,并且易于理解和实现。通过使用滑动窗口算法,我们可以高效地找到给定字符串中不包含重复字符的最长子串。