📅  最后修改于: 2023-12-03 15:12:40.015000             🧑  作者: Mango
给定一个字符串s和一组字符集合,编写一个函数来查找s中是否存在可以由字符集合中的字符组成的一个完整的字符串。
例如,给定s =“ADOBECODEBANC”,字符集合为['A','B','C'], 函数应该返回“BANC”。
如果没有这样的字符串,返回空字符串""。
这是一道非常经典的滑动窗口问题,可以使用双指针实现。设置左右指针left和right,初始都为0。
首先,将字符集合转化为一个字典,其中键为字符,值为该字符在字符集合中出现的次数。
接下来,进入循环,右指针依次向后移动,将遇到的字符及其出现次数记录在字典t中。当t中的所有键都在字符集合中出现,并且值都不超过字符集合中该键的值时,说明找到了符合条件的字符串。
此时,可以尝试将左指针尽可能的右移,直到找到了一个字符,它在t中的值不小于在字符集合中的值,然后更新找到的字符串。然后,左指针再右移一格,右指针继续向后移动,也就是回到第二步,直到右指针移动到字符串的末尾。
时间复杂度为O(n),空间复杂度为O(k),其中n为字符串s的长度,k为字符集合的大小。
def minWindow(s: str, t: str) -> str:
# 统计字符集合中每个字符出现的次数
dic = {}
for c in t:
if dic.get(c) is None:
dic[c] = 1
else:
dic[c] += 1
# 初始化左右指针及其他相关变量
left = right = 0
count = len(t)
ans = ""
min_len = float("inf")
while right < len(s):
# 如果right指向的字符在字典中存在
if dic.get(s[right]) is not None:
# 如果该字符出现的次数还没达到要求,则count要减一
if dic.get(s[right]) > 0:
count -= 1
dic[s[right]] -= 1 # 将该字符出现次数减一
# 如果count等于0了,则说明所有字符都已经匹配成功了
while count == 0:
# 找到了一个符合要求的字符串,更新答案
if min_len > right - left + 1:
ans = s[left: right + 1]
min_len = right - left + 1
# 如果left指向的字符在字典中存在
if dic.get(s[left]) is not None:
# 如果该字符的出现次数已经和在字符集合中出现的次数相等了,
# 则count要加一,因为现在要删除了一个这样的字符。
if dic.get(s[left]) == 0:
count += 1
dic[s[left]] += 1 # 将该字符出现次数加一
# 左指针右移
left += 1
# 右指针右移
right += 1
return ans
该函数的输入为两个字符串s和t,返回一个字符串。使用时,只需要将输入参数替换为实际的字符串即可。