BM90 最小覆盖子串(python)

题目

题目链接
两个字符串:S,T,要求找出S中【包含T中所有字母(顺序可以不一致)】的最短子串
在这里插入图片描述

思路

双指针+哈希表
  • 使用2个指针i,j,初始时均指向0,S[i:j+1]为当前正在处理的子串

  • 使用一个字典needDict作为哈希表,存放T中所有字母以及出现次数
    T='ZXYZ'needDict={‘Z’:2,'Y':1,'X':1}
    在遍历S取子串S[i:j+1]的过程中,needDict中键对应的值可能会变成以下情况:

>0表示子串中还缺少这个字母
=0表示子串中这个字母数量正好足够
<0表示子串中这个字母数量比T中的多

  • matched记录当前已经匹配的字母数,当matched=T的长度时,说明当前子串S[i:j+1]满足题目需要
  • minLendst分别记录符合要求的最短子串长度和最短子串,minLen初始为无穷大,dst初始为空串

遍历S取子串:j每次+1,到S末尾停止

  1. S[j]needDict中, 将needDict中键S[j]对应的值-1
    若此时needDict[S[j]]>=0,说明本次匹配到一个还缺少的字母,令matched+1

  2. 若matched=T的长度,说明当前字符串满足了题目需要,可以让i不断右移缩短子串长度,同时维护needDict[S[i]]的值,直到子串S[i:j+1]不再满足要求:
    S[i]needDict中,把needDict[S[i]]-1,如果这个操作使得needDict[S[i]]>0,说明i右移移走S[i]这个字母会使得S[i:j+1]不再满足题目需要,此时更新最短的子串,并令matched-1

代码

class Solution:
    def minWindow(self, S, T):
    	# 空串,或者S比T还短
        if not S or not T or len(S)<len(T):
            return ''
            
        i,j=0,0
        minLen=float('inf')
        dst=''
        matched=0
        needDict={}
        
        # 根据T初始化哈希表
        for char in T:
            needDict[char]=needDict.get(char,0)+1
		
		# 对S取子串
        for j in range(len(S)):
        	# 当前字母是T中的字母(①可能子串中还缺少这个字母,②也可能数量已经够了,但都要令键对应的值-1)
            if S[j] in needDict:
                needDict[S[j]] -= 1
                # 如果是前一种情况,让matched+1表示匹配了一个尚需要的字母
                if needDict[S[j]]>=0:
                    matched+=1
                    
			# 当前子串满足需要,更新最短子串
			# 并让i右移直到当前子串不再符合需要
            while matched==len(T):
                if S[i] in needDict:
                    if j+1-i<minLen:
                        dst=S[i:j+1]
                        minLen=j+1-i
                    needDict[S[i]]+=1
                    if needDict[S[i]]>0:
                        matched-=1
                i+=1
        return dst
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值