📜  最大非重复元素(1)

📅  最后修改于: 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)$。滑动窗口算法的思路是这样的:

  1. 用两个指针表示当前子串的左右边界,初始值都为 0。
  2. 将右指针移动到字符串末尾,如果当前子串包含重复字符,则将左指针移动到重复字符的下一个位置。
  3. 记录此时的子串长度和最大子串长度,将右指针继续向前移动,重复上述过程。

具体实现可以参考下面的 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)$,并且可以通过优化进一步提高效率。掌握这个算法问题,对于提高编程能力和解决实际问题都非常有帮助。