📜  数据结构 |杂项 |问题 9(1)

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

数据结构 | 杂项 | 问题 9

在程序开发中,面对各种复杂的数据结构和算法问题是常见的挑战。本文将介绍一个常见的问题,以及解决该问题的一些方法。

问题描述

问题 9:给定一个字符串,找到其中最长的不包含重复字符的子串。例如,在字符串 "abcabcbb" 中,最长的不包含重复字符的子串为 "abc"。

解决方法

1. 暴力法

暴力解决该问题的方法是枚举所有可能的子串并比较它们是否重复。时间复杂度为 $O(n^3)$ ,容易超时。

2. 滑动窗口

滑动窗口是一种比较高效的解决方法。我们可以用两个指针 left 和 right 来划定一个窗口,然后根据窗口中的字符判断是否重复,如果重复,则移动 left ,否则移动 right。

时间复杂度为 $O(n)$ ,可以通过该方法解决该问题。

def lengthOfLongestSubstring(s: str) -> int:
    n = len(s)
    ans = 0
    left, right = 0, 0
    visited = set()

    while left < n and right < n:
        if s[right] not in visited:
            visited.add(s[right])
            right += 1
            ans = max(ans, right - left)
        else:
            visited.remove(s[left])
            left += 1

    return ans

3. 动态规划

我们可以用一个长度为 $n$ 的列表 dp 来表示以每个字符为结尾的最长不重复子串的长度。我们可以枚举字符串中的每个字符,然后判断它是否在以前一个字符结尾的不重复子串中出现过,如果出现过,则从该位置开始重新计算不重复子串的长度,否则将以前一个字符结尾的最长不重复子串长度加 1。

时间复杂度为 $O(n)$ ,可以通过该方法解决该问题。

def lengthOfLongestSubstring(s: str) -> int:
    n = len(s)
    if n == 0:
        return 0
    dp = [0] * n
    dp[0] = 1
    visited = {s[0]}
    ans = 1

    for i in range(1, n):
        if s[i] not in visited:
            visited.add(s[i])
            dp[i] = dp[i - 1] + 1
        else:
            j = i - 1
            while j >= i - dp[i - 1]:
                if s[j] == s[i]:
                    break
                visited.remove(s[j])
                j -= 1
            dp[i] = i - j
        ans = max(ans, dp[i])

    return ans
总结

本文介绍了一个常见的字符串问题,以及三种解决方法:暴力法、滑动窗口和动态规划。其中,滑动窗口和动态规划是比较高效的解决方法。在实际开发中,应该根据实际情况来选择合适的解决方法。