最小覆盖子串

思路

滑动窗口双指针
变量:
left, right为当前窗口的开始和结尾索引
dict_s, dict_p分别为待匹配字符串和模式串相关的字典,他们的key是模式串的各个字符,value为各个字符在字符串中出现的次数
valid为当前窗口待匹配串和模式串已经匹配上的字符的种数,不是个数
start为当前的最短的覆盖子串的起始索引
min_len为当前的最短的覆盖子串的长度
string为待匹配串
pat为模式串
前置工作:
遍历pat串,填充dict_p。具体是,统计pat中各个字符出现的次数,用dict_p保存。
过程:
1,left,right都从0开始,滑动对象是string
2,right往右滑动,令当前字符为c,如果c在dict_p中,dict_s[c] += 1。如果dict_p[c]==dict_s[c], valid+=1
3,如果valid等于len(dict_p),说明当下窗口有符合的覆盖子串。如果当前窗口长度小于min_len,则令start=left, len_min为当前窗口长度。left向右滑动,令pass_c为string[left-1],如果pass_c在dict_p中,那么dict_s[pass_c]-=1,如果dict_s[pass_c]<dict_p[pass_c],valid-=1。重复这个过程,直到valid不等于len(dict_p),再回到步骤2。
时间复杂度O(n)
空间复杂度O(n)

链接

最小覆盖子串

代码

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param S string字符串 
# @param T string字符串 
# @return string字符串
#
class Solution:
    def minWindow(self , S: str, T: str) -> str:
        # write code here
        string, pat = S, T 

        dict_s = {}
        dict_p = {}

        for c in pat:
            if c not in dict_p:
                dict_p[c] = 1
            else:
                dict_p[c] += 1
        len_p = len(pat)
        valid = 0
        left = 0
        start = 0
        min_len = float("inf")
        for right in range(len(string)):
            c = string[right]
            if c in dict_p:
                # print(c)
                if c not in dict_s:
                    dict_s[c] = 1 
                else:
                    dict_s[c] += 1 
                if dict_s[c] == dict_p[c]:
                    valid += 1
                # print(valid, len_p)
                while valid == len(dict_p):
                    cur_len = right-left+1
                    if cur_len < min_len:
                        min_len = cur_len
                        start = left
                    left += 1
                    pass_c = string[left-1]
                    if pass_c in dict_p:
                        dict_s[pass_c] -= 1
                        if dict_s[pass_c] < dict_p[pass_c]:
                            valid -= 1

        if min_len == float("inf"):
            return ""
        return string[start:start+min_len]
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值