leetcode(32)-最小覆盖子集

最小覆盖子集

给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。

示例:

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

提示:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

from collections import defaultdict

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        sets = set([chr for chr in t])
        maps = defaultdict(lambda :0)
        needs = defaultdict(lambda: 0)
        for each in t:
            needs[each] +=1
        up = 0
        down = 0
        if s[0] in sets:
            maps[s[0]] +=1
        def check():
            for each in sets:
                if each in maps.keys() and maps[each]>=needs[each]:
                    pass
                else:
                    return False
            return True
        min_len = 1<<31
        min_up, min_down = 0,0
       
        if check():
           return ''.join([ch for ch in sets])
        while  not check() and down<len(s)-1:
            down+=1
            if s[down] in sets:
                maps[s[down]] += 1
                while check() and up<=down:
                    if s[up] in sets:
                        if min_len>down-up+1:
                            min_up = up
                            min_down = down
                            min_len = down-up+1
                        maps[s[up]]-=1
                    up += 1
        if min_len>len(s):
            return ''
        return s[min_up:min_down+1]

更好的check方式

from collections import defaultdict

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        need=defaultdict(int)
        for c in t:
            need[c]+=1
        needCnt=len(t)
        i=0
        res=(0,float('inf'))
        for j,c in enumerate(s):
            if need[c]>0:
                needCnt-=1
            need[c]-=1
            if needCnt==0:       #步骤一:滑动窗口包含了所有T元素
                while True:      #步骤二:增加i,排除多余元素
                    c=s[i] 
                    if need[c]==0:
                        break
                    need[c]+=1
                    i+=1
                if j-i<res[1]-res[0]:   #记录结果
                    res=(i,j)
                need[s[i]]+=1  #步骤三:i增加一个位置,寻找新的满足条件滑动窗口
                needCnt+=1
                i+=1
        return '' if res[1]>len(s) else s[res[0]:res[1]+1]


posted @ 2020-09-13 15:35  木子士心王大可  阅读(377)  评论(0)    收藏  举报