[LeetCode]76. 最小覆盖子串

题目

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。

示例:

输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

说明:

  • 如果 S 中不存这样的子串,则返回空字符串 “”。
  • 如果 S 中存在这样的子串,我们保证它是唯一的答案。

解题思路

定义 left, right 分别指向滑动窗口的左右边界,子字符串为 s[left, right) 左闭右开区间。使用 right 指针向右搜索,同时要记录在 s[left, right) 这个区间覆盖了多少个 t 中的元素。如果在 s[left,right) 内,覆盖了所有 t 的元素,说明这个区间是符合要求的一个区间。此时 right 指针再向右移动已经没有意义。现在要移动 left 指针,直至 s[left,right) 子字符串不能覆盖 t 。
在 s[left, right) 区间内的元素出现个数应该把 t 中所有的元素都包含,所以我们定义 t_dic 字典变量保存 t 中的元素出现次数,s_dic 字典变量保存 s[left, right) 滑动窗口中的相应字符出现的次数。 count 变量储存 s[left, right) 闭区间中已经覆盖了 t 中的多少个元素,如果 cnt == len(t_dic) 说明该子字符串覆盖了 t 中所有字符,这时已经得到一个可行的覆盖子串,可以开始收缩窗口了,以便得到最小覆盖子串。
在移动 left 指针收缩窗口的时候要注意存储最短的子串,使用的 minLen 变量存储当前满足题目要求的最短子串长度。当某个子字符串区间满足要求时,根据minLen更新最终的最小覆盖子串。

代码

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        need=collections.defaultdict(int)
        m = len(s)
        n = len(t)
        # 滑动窗口中相应出现的字符及其对应的个数
        s_dic = {}
        # t中出现的字符及其对应的个数
        t_dic = {}
        # 滑动窗口左右位置,左闭右开区间 [left, right)
        left = 0
        right = 0
        # 滑动窗口中满足t_dic中条件的字符个数
        count = 0
        # 记录最小覆盖子串的起始索引和长度
        start = 0
        minlen = float('inf')
        # 将t中的字符加入t_dic字典
        for i in t:
            if i in t_dic: 
                t_dic[i] += 1
            else: 
                t_dic[i] = 1
        while right<m:
            # c是将移入窗口的字符
            c = s[right]
            # 右移窗口
            right += 1
            # 滑动窗口内数据更新
            if c in t_dic:
                if c in s_dic:
                    s_dic[c] += 1
                else:
                    s_dic[c] = 1
                if s_dic[c] == t_dic[c]:
                    count += 1
            # 判断左侧窗口是否要收缩
            while count==len(t_dic):
                # 更新最小覆盖子串的起始索引和长度
                if right-left<minlen:
                    start = left
                    minlen = right-left
                # d是将移出窗口的字符
                d = s[left]
                # 左移窗口
                left += 1
                # 滑动窗口内数据更新
                if d in t_dic:
                    if s_dic[d] == t_dic[d]:
                        count -= 1
                    s_dic[d] -= 1
        return '' if minlen == float('inf') else s[start:start+minlen]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章