📜  门| GATE-CS-2003 |第 32 题(1)

📅  最后修改于: 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,返回一个字符串。使用时,只需要将输入参数替换为实际的字符串即可。