掌握双指针技巧,解锁 LeetCode 之无重复字符的最长字符串
2023-12-01 20:24:07
引言
在竞技编程和面试场景中,LeetCode 已成为一道绕不开的坎。解决 LeetCode 问题不仅可以检验你的编程能力,还能让你接触到各种算法和数据结构的实际应用。其中,双指针技巧是 LeetCode 中的常见套路,掌握它能有效地解决许多看似棘手的问题。今天,我们将以一道 Leetcode 经典题目——无重复字符的最长字符串,来深入解析双指针的精髓。
问题
给定一个字符串 s,找出不包含重复字符的最长子串的长度。
思路分析
乍一看,这道题似乎需要使用蛮力法,遍历字符串中的所有子串并检查它们是否不包含重复字符。然而,这样做的时间复杂度为 O(n^2),对于大规模数据来说过于耗时。
因此,我们需要考虑更有效的方法。双指针技巧便是一种可行的方案。双指针法通过使用两个指针在字符串中移动来寻找解决方案。
双指针解法
在双指针解法中,我们使用两个指针 left 和 right 来定义子串的范围。初始时,left 和 right 都指向字符串的开头。我们不断移动 right 指针向右,同时检查子串是否包含重复字符。如果包含,则移动 left 指针向右,直到子串中不再包含重复字符。
具体实现如下:
- 初始化 left 和 right 指针,指向字符串的开头。
- 移动 right 指针向右,直到找到一个重复的字符。
- 如果找到重复字符,移动 left 指针向右,直到子串中不再包含重复字符。
- 更新最长子串的长度。
- 重复步骤 2-4,直到 right 指针到达字符串的末尾。
代码实现
def length_of_longest_substring(s):
# 记录字符最后出现的位置
char_index = {}
# 初始化双指针
left = right = max_length = 0
while right < len(s):
# 如果字符已出现过,更新 left 指针
if s[right] in char_index and char_index[s[right]] >= left:
left = char_index[s[right]] + 1
# 更新字符最后出现的位置
char_index[s[right]] = right
# 更新最长子串长度
max_length = max(max_length, right - left + 1)
# 移动 right 指针
right += 1
return max_length
优化
上述解法的时间复杂度为 O(n),其中 n 为字符串的长度。为了进一步优化,我们可以使用滑动窗口优化技术。滑动窗口优化通过维护一个窗口,窗口内的字符不包含重复字符,随着 right 指针向右移动,窗口不断滑动。
滑动窗口解法
def length_of_longest_substring(s):
# 记录字符最后出现的位置
char_index = {}
# 初始化双指针和窗口大小
left = right = 0
max_length = 0
while right < len(s):
# 如果字符已出现过,缩小窗口
if s[right] in char_index:
left = max(left, char_index[s[right]] + 1)
# 更新字符最后出现的位置
char_index[s[right]] = right
# 更新窗口大小
max_length = max(max_length, right - left + 1)
# 移动 right 指针
right += 1
return max_length
结语
双指针技巧在 LeetCode 中广泛应用,通过巧妙地利用两个指针,我们可以有效地解决许多问题。无重复字符的最长字符串问题是一个经典的双指针问题,通过掌握双指针的精髓,我们不仅可以轻松解决这道题,还能为解决更多复杂问题打下坚实的基础。
拓展阅读
SEO 优化