76.最小覆盖子串

本文介绍了如何使用Python实现一个算法来找到字符串s中最小子串,该子串包含字符串t的所有字符,同时考虑了重复字符的要求。通过创建字典和滑动窗口的概念,作者提供了一段代码示例,并对其进行了优化。
摘要由CSDN通过智能技术生成

·题目描述

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

 

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
 

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。
示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

·解题思路:

1.需要字符类型和个数——考虑创建字典

创建两个字典,一个用于存放目标所需要的字母和个数;一个用来记录滑动窗口所涉及的字母和个数

2.需要记录窗口的起始——考虑滑动窗口

先滑动end,即窗口的右端,遍历记录字符。当满足所需要求的时候,再考虑滑动窗口的左端,缩短窗口长度,获取最小窗口

3.循环判断条件:

当滑动窗口包含目标窗口的时候,进入循环条件,移动左端指针。

·代码:

class Solution:
    def isContains(self,cur_str,target_str):
        for key in target_str:
            if cur_str[key] < target_str[key]:
                return False
        return True

    def minWindow(self, s: str, t: str) -> str:
        need = Counter(t)
        char_map = {}
        for key in need :
            if key not in char_map:
                char_map[key] = 0

        star = 0
        res = ""
        minlength = float('inf')
        for end in range(len(s)):
            if s[end] in need:
                char_map[s[end]] += 1
            end += 1
            while self.isContains(char_map,need):
                curlength = end - star + 1
                if curlength < minlength:
                    minlength = curlength
                    res = s[star: end+1]

                if s[star] in need:
                    char_map[s[star]] -= 1
                star -= 1
        return res

·代码优化

每次切片存储并且使用额外函数判断循环条件过于麻烦,考虑使用target_num对所需字符串个数进行计数。

    def minWindow(self, s: str, t: str) -> str:
        need ,windows = Counter(t),{}
        for key in need :
            if key not in windows:
                windows[key] = 0

        min_star ,min_end = 0,0
        min_length = float('inf')
        target_num = len(t)
        star = 0
        for end in range(len(s)):
            if s[end] in need:
                windows[s[end]] += 1
                if windows[s[end]] <= need[s[end]]:
                    target_num -= 1

            while target_num == 0:
                cur_length = end - star + 1
                if cur_length < min_length:
                    min_length = cur_length
                    min_star = star
                    min_end = end

                if s[star] in need:
                    windows[s[star]] -= 1
                    if windows[s[star]] < need[s[star]]:
                        target_num += 1

                star += 1

        if min_length == float('inf'):
            return ''
        return s[min_star : min_end+1]

————两个注意的点————

                if windows[s[end]] <= need[s[end]]:
                    target_num -= 1

这里表示,当滑动窗口中字符个数小于或等于所需要个数的时候,所需要的target_num 减一。这是因为该语句end] in need的条件下,也就是说,现在所放入的是s[end]一定是need中的字符,所以num可以减一。

若是改为windows[s[end]] >= need[s[end]],就会出现因为多余字符导致target_num 减为0 的情况。

                if s[star] in need:
                    windows[s[star]] -= 1
                    if windows[s[star]] < need[s[star]]:
                        target_num += 1

结束时候的判断条件就变为了,windows[s[star]] >= need[s[star]],这是因为,移动左窗口的时候,会导致所需要的元素滑出,从而影响所需要的target_num

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值