[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]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章