📌  相关文章
📜  具有最大唯一字符数的字符串(1)

📅  最后修改于: 2023-12-03 15:22:35.293000             🧑  作者: Mango

具有最大唯一字符数的字符串

在字符串中找到一个长度最长的子串,满足该子串中的字符不重复。

例如:

输入: aghdgfhk
输出: hdgfk (长度为5)
解决方案
暴力解法

最简单的做法是暴力枚举所有可能的子串,并检查子串中是否有重复的字符。这种方法的时间复杂度为O(n^3),虽然简单易懂,但效率较低,仅适用于较短的字符串。

def longest_non_repeat_substring(s: str) -> str:
    n = len(s)
    ans = ""
    for i in range(n):
        for j in range(i+1, n+1):
            if len(set(s[i:j])) == j-i:
                if len(ans) < len(s[i:j]):
                    ans = s[i:j]
    return ans
滑动窗口

由于暴力解法效率较低,我们需要尝试更快的算法。滑动窗口是一种常见的解题方法,可以在O(n)的时间内解决此问题。我们使用两个指针,左右指针构成一个窗口,窗口中的字符不重复,右指针向右移动时,窗口向右滑动,左指针向右移动时,窗口缩小。我们根据窗口中字符数量的多少,判断是否更新最长子串。

例如:输入 'dababcd'

  1. 使用一个字典记录窗口中字符的出现次数,例如进入第一个窗口 'dababc',字典记录的是:{'d':1, 'a':2, 'b':2, 'c':1}。
  2. 右指针向右移动到位置6,进入下一个窗口 'abcd',此时字典记录的是:{'a':1, 'b':1, 'c':1, 'd':1}。
  3. 发现窗口中字符不重复,更新最长子串。
  4. 左指针向右移动1位,进入第三个窗口 'babcd',此时字典记录的是:{'a':1, 'b':2, 'c':1, 'd':1}。
  5. 发现窗口中字符有重复,左指针向右移动1位,从字典中删除左指针指向的字符,进入下一个窗口 'abcd'。
def longest_non_repeat_substring(s: str) -> str:
    n = len(s)
    ans = ""
    i = 0
    j = 0
    seen = set()
    while i < n and j < n:
        if s[j] not in seen:
            seen.add(s[j])
            j += 1
            ans = max(ans, s[i:j], key=len)
        else:
            seen.remove(s[i])
            i += 1
    return ans
时间复杂度

滑动窗口算法的时间复杂度是O(n),空间复杂度是O(min(n, m)),其中m是字符集的大小。如果字符集大小是常数级别,那么空间复杂度是O(1)。我们可以说这是一种线性时间复杂度的算法,算法的实际速度由输入字符串的长度决定。