📅  最后修改于: 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),但代码更清晰简单。