76. 最小覆盖子串!!(滑动窗口)

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

示例:

输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"

说明:

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

困难
【分析】滑动窗口法。


外循环 right
内循环 left
当外循环循环到count==count_n and left<=right时,才进内循环
res=(start-end+1的长度,left,right)


dict_t 记录t中各字母出现的次数
count_n 记录t中不重复字母的个数 ,比如t=“abcdd”,count_n=4


字符char → 先对right外循环
dic_window 记录窗口内该字母出现的次数
count 记录 如果字母出现的次数一旦达到dict_t中满足的情况时+1(当count记录的次数等count_n时,说明出现一段窗口满足总情况了。进入内循环再作处理)


进入内循环,对大窗口进行收缩:
char → 对left内循环
end记录相应right的char在s中的下标
start记录相应left的char在s中的下标
如果窗口长度小于已知记录的长度,则刷新记录res:(start-end+1,start,end)
dic_window[char]-1 窗口向内收缩
窗口收缩时同时记录count :当dic_window[char] < dict_t[char]时

当count!=count_n and left>right时,跳出内循环,此时res已经记录下符合题意的最小长度的end-start+1了。


然后再作外循环…


总体思路: 先对right作循环当窗口满足覆盖t的字串时,进入内循环对left作循环,窗口向内收缩找到最小长度的覆盖子串。

from collections import Counter
class Solution(object):
    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        if not t or not s:
            return ""
        if len(t)>len(s):
            return ""
        
        dic_t=Counter(t)
        count_n=len(dic_t)
        
        s_lst=[]
        for i,char in enumerate(s):
            if char in t:
                s_lst.append((i,char))
         
        res=float("inf"),0,0
        left,right=0,0
        dic_window={}
        count=0
        
        while right<len(s_lst):
            char=s_lst[right][1]
            dic_window[char]=dic_window.get(char,0)+1
            if dic_window[char]==dic_t[char]:
                count+=1
            while left<=right and count==count_n:
                char=s_lst[left][1]
                start=s_lst[left][0]
                end=s_lst[right][0]
                if end-start+1<res[0]:
                    res=end-start+1,start,end
                dic_window[char]-=1
                if dic_window[char]<dic_t[char]:
                    count-=1
                left+=1
            right+=1        
        return s[res[1]:res[2]+1] if res[0]!=float("inf") else ""

:统计字符出现的个数,返回字典:

from collections import Counter
t="abac"
dic_t=Counter(t)
t="abac"
dic_t={}
for i in t:
    dic_t[i]=dic_t.get(i,0)+1

注2:一开始也想到说把t中的单词凡是在中出现的位置取出来,但是没有联想到滑窗的方法,一开始也只是取出来的位置放在一个dict中,这样应该也能做出来,以后可以想想怎么做:

        s = "ADOBECODEBANC"; t = "ABC"
        from collections import defaultdict
        dic_s=defaultdict(list)
        for i,char in enumerate(s):
            if char in t:
                dic_s[char].append(i)

dic_s=defaultdict(list, {‘A’: [0, 10], ‘B’: [3, 9], ‘C’: [5, 12]}),这个或者可以用最小路径来做?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值