76. 最小覆盖子串

在这里插入图片描述
思路

用字典dict1来记录t字符情况(次数),用c来记录窗口滑动时覆盖字符情况,字符次数全都初始化为0。l表示滑动窗口初始位置,r表示窗口最末位置,flag表示当前窗口是否全部包含覆盖字符,是True,否:False,re表示最小覆盖子串
窗口滑动:
扩大窗口时(r向右移动):
先判断当前扩大的值是否是覆盖的值,是则c对应的键值+1,接着判断此时滑动窗口是否都包含了覆盖字符,不包含则继续扩大
包含,则尝试缩小窗口:
此时,若s[l]是属于覆盖字符:
则要去判断缩小窗口(l向右移动)后的窗口还能全覆盖字符t吗,如果覆盖则继续缩小窗口,但缩小后不能覆盖,则说明当前窗口已经是覆盖字符的最小窗口,不能再缩小了,只能扩大窗口
若s[l]不是覆盖字符,则可缩小窗口
if len(re)==0 or len(re)>=r-l+1:加上len(re)==0原因:由于最小覆盖字符初始时设置为’ ',则第一次获取到覆盖窗口时,应直接将窗口的字符串赋值给re

复杂度
时间复杂度: O(n)

代码:

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        if len(t)>len(s):
            return ""
        if t==s:
            return t
        l=0
        r=0
        dict1={}
        c={}
        re=""
        for i in t:
            if i not in dict1:
                dict1[i]=1
                c[i]=0
            else:
                dict1[i]+=1
        while r<len(s):
            if s[r] in dict1:
                c[s[r]]+=1
            flag=True
            for i in dict1:
                if dict1[i]>c[i]:
                    flag=False
                    break
            while flag:
                if len(re)==0 or len(re)>=r-l+1:
                    re=s[l:r+1]
                if s[l] in dict1:
                    #正好是包含的值
                    if c[s[l]]>dict1[s[l]]:
                        #可向右滑动
                        c[s[l]] -= 1
                        l+=1
                    else:
                        flag=False
                else:
                    #可向右滑动
                    l+=1    
            r+=1
        return re

ps:

关于字典的比较:python2是支持的,python3不支持

python2使用字典比较的时候,可以用c>dict1来进行判断缩小窗口,之前用这个方法有问题,然后用pycharm调试时报错了(python3版本),所以改了方法,在用python2可以试一试

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

### Java 实现最小覆盖子串算法 对于最小覆盖子串问题,在字符串 `s` 中找到能覆盖字符串 `t` 所有字符的最小子串是一项挑战。下面展示了一个基于滑动窗口技术来解决问题的方法[^1]。 ```java import java.util.*; public class MinWindowSubstring { public String minWindow(String s, String t) { if (s == null || t == null || s.isEmpty() || t.isEmpty()) return ""; Map<Character, Integer> targetCount = new HashMap<>(); for (char c : t.toCharArray()) { targetCount.put(c, targetCount.getOrDefault(c, 0) + 1); } int requiredChars = targetCount.size(); int formed = 0; Map<Character, Integer> windowCounts = new HashMap<>(); int left = 0, right = 0; int[] ans = {-1, 0, 0}; while (right < s.length()) { char character = s.charAt(right); windowCounts.put(character, windowCounts.getOrDefault(character, 0) + 1); if (targetCount.containsKey(character) && windowCounts.get(character).intValue() == targetCount.get(character).intValue()) { formed++; } while (left <= right && formed == requiredChars) { character = s.charAt(left); if (ans[0] == -1 || right - left + 1 < ans[0]) { ans[0] = right - left + 1; ans[1] = left; ans[2] = right; } windowCounts.put(character, windowCounts.get(character) - 1); if (targetCount.containsKey(character) && windowCounts.get(character).intValue() < targetCount.get(character).intValue()) { formed--; } left++; } right++; } return ans[0] == -1 ? "" : s.substring(ans[1], ans[2] + 1); } } ``` 上述代码实现了滑动窗口方法,通过两个指针(`left`, `right`)维护当前考察的窗口范围,并利用哈希表记录目标字符串`t`中的字符频率以及当前窗口内的字符频率。当窗口内包含了足够的`t`中字符时尝试收缩左边界以优化解的空间大小[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值