📌  相关文章
📜  字符串的最小长度具有给定的字符串的所有排列。(1)

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

字符串的最小长度具有给定的字符串的所有排列

给定一个字符串,要求找到一个最小长度的字符串,使得其包含给定字符串的所有排列。

解决方案

我们可以使用滑动窗口来解决这个问题。

具体来说,假设给定字符串为s,我们可以先用一个哈希表记录下s中每个字符出现的次数。

然后,我们用一个滑动窗口[left, right],表示字符串中的一个子串。我们先将右指针right移动,直到滑动窗口中包含了s中所有字符。然后,我们不断将左指针left向右移动,直到滑动窗口中不再包含s中所有字符。在这个过程中,我们记录下每个子串的长度,并取最小值即可。

具体实现可见以下代码片段:

def minWindow(s: str, t: str) -> str:
    # 记录t中每个字符出现的次数
    dict_t = {}
    for c in t:
        dict_t[c] = dict_t.get(c, 0) + 1

    # 初始化滑动窗口
    left, right = 0, 0
    counter = len(t)
    min_len = float('inf')
    res = ''

    # 移动滑动窗口
    while right < len(s):
        # 如果当前字符在t中出现过,则将其次数减1
        if s[right] in dict_t:
            dict_t[s[right]] -= 1
            if dict_t[s[right]] >= 0:
                counter -= 1

        right += 1

        # 当滑动窗口中包含了t的所有字符时
        while counter == 0:
            # 记录当前子串的长度,并更新最小值
            if right - left < min_len:
                min_len = right - left
                res = s[left: right]

            # 如果当前字符在t中出现过,则将其次数加1
            if s[left] in dict_t:
                dict_t[s[left]] += 1
                if dict_t[s[left]] > 0:
                    counter += 1

            left += 1

    return res
思考

以上代码的时间复杂度为O(n),其中n为字符串s的长度。这是因为我们最多只会遍历字符串s两次。具体来说,我们用右指针right遍历一遍字符串s,然后用左指针left遍历一遍字符串s。

然而,以上代码中的哈希表维护比较繁琐。我们可以使用Python自带的Counter数据结构来简化代码。

具体实现可见以下代码片段:

from collections import Counter

def minWindow(s: str, t: str) -> str:
    # 统计t中每个字符出现的次数
    dict_t = Counter(t)

    # 初始化滑动窗口
    left, right = 0, 0
    counter = len(t)
    min_len = float('inf')
    res = ''

    # 移动滑动窗口
    while right < len(s):
        # 如果当前字符在t中出现过,则将其次数减1
        if s[right] in dict_t:
            dict_t[s[right]] -= 1
            if dict_t[s[right]] >= 0:
                counter -= 1

        right += 1

        # 当滑动窗口中包含了t的所有字符时
        while counter == 0:
            # 记录当前子串的长度,并更新最小值
            if right - left < min_len:
                min_len = right - left
                res = s[left: right]

            # 如果当前字符在t中出现过,则将其次数加1
            if s[left] in dict_t:
                dict_t[s[left]] += 1
                if dict_t[s[left]] > 0:
                    counter += 1

            left += 1

    return res

以上代码中的时间复杂度仍为O(n),但代码更清晰简单。