📅  最后修改于: 2023-12-03 15:40:15.279000             🧑  作者: Mango
在计算机科学中,最大非重复元素是指一个集合中不包括任何重复元素的最大子集。在大多数情况下,这个问题是指寻找一个字符串中的最长的子串,该子串不包含重复的字符。
给定一个字符串 s,请找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
示例 4:
输入: s = ""
输出: 0
最直接的解法是枚举所有子串,并验证每个子串是否包含重复字符。这个方法需要 $O(n^3)$ 的时间复杂度,显然不可行。
滑动窗口是一个非常高效的算法,可以将 $O(n^2)$ 的时间复杂度降低到 $O(n)$。滑动窗口算法的思路是这样的:
具体实现可以参考下面的 Python 代码:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
# 使用一个哈希集合来记录字符是否重复
hash_set = set()
# 定义左右指针和最大子串长度
left, right, max_len = 0, 0, 0
while left < n and right < n:
# 如果字符未重复,则将右指针向右移动
if s[right] not in hash_set:
hash_set.add(s[right])
right += 1
max_len = max(max_len, right - left)
# 如果字符重复,则将左指针向右移动
else:
hash_set.remove(s[left])
left += 1
return max_len
上面的代码中,我们使用了一个哈希集合来记录字符是否重复。在移动右指针时,如果新的字符未重复,则将其添加到集合中,并更新最大子串长度。如果新的字符重复,则一直将左指针向右移动,直到重复字符的下一个位置。
上面的滑动窗口算法可以被优化,因为当左指针跳过重复字符时,其实可以直接跳到重复字符的下一个位置,而不是一个一个地移动。我们可以使用一个哈希表来记录字符的位置,从而避免反复查找。
具体实现可以参考下面的 Python 代码:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
# 使用一个哈希表来记录字符位置
hash_map = {}
# 定义左指针和最大子串长度
left, max_len = 0, 0
for right in range(n):
# 如果字符已经出现过,则更新左指针的位置
if s[right] in hash_map and hash_map[s[right]] >= left:
left = hash_map[s[right]] + 1
# 更新哈希表和最大子串长度
hash_map[s[right]] = right
max_len = max(max_len, right - left + 1)
return max_len
在上面的代码中,我们使用了一个哈希表来记录字符位置。在移动右指针时,如果新的字符已经存在于哈希表中,并且其位置在当前子串范围内,则更新左指针的位置。
最大非重复元素是经典的算法问题,在面试中也非常常见。使用滑动窗口可以将时间复杂度降低到线性时间 $O(n)$,并且可以通过优化进一步提高效率。掌握这个算法问题,对于提高编程能力和解决实际问题都非常有帮助。