5.3.76. 最小覆盖子串

思路:

滑动窗口之最小滑窗最小滑窗

字符串麻烦在组织答案,要用substr这些东西

储备:

76. 最小覆盖子串 - 力扣(LeetCode)

评论区里有c++版本的答案

问题重点:

1、它是先把所有需要的量,所有的需求,比如t的长度等等求出来。遍历时一个一个减。

那反过来呢?累加已有的字符数量看是否达到cnt?

cnt==0当条件比较方便写吧。

最后:

unordered_map做哈希:

class Solution {
public:
    string minWindow(string s, string t) {//unordered_map做哈希
        int n=s.size();
        unordered_map<int,int> num;//哈希

        int cnt=t.size();//所需长度
        for (int i=0;i<cnt;i++) num[t[i]]++;

        //答案所需变量
        int res=INT_MAX;//因为是最小滑窗
        int st=0;

        for (int i=0,j=0;i<n;i++) {//遍历s
            if (num[s[i]]>0) cnt--;//检查s的当前字符。合要求的话需求量减少。
            num[s[i]]--;//加入窗口,攒着s已经有的字符数量

            if (cnt==0) {//如果满足了t的要求
                while (j<i && num[s[j]]<0) {//移动窗口左边界。求满足要求的最小长度。存货num减少
                    num[s[j]]++;
                    j++;
                }
                //得到了满足条件的最短窗口。尝试更新
                if (res>i-j+1) {
                    res=i-j+1;
                    st=j;
                }
                //增加需求,寻找下一个合法序列。
                num[s[j]]++;
                cnt++;
                j++;
            }
        }
        return res==INT_MAX ? "" : s.substr(st,res);
    }
};

计数数组做哈希:

class Solution {
public:
    string minWindow(string s, string t) {
        int n=s.size();
        vector<int> num(128,0);//ascii码0:48-57,A65-90,a97-122。计数数组做哈希。
        for (char c:t) {//范围for
            num[c]++;//
        }
        int cnt=t.size();//子串需要的数量

        //答案所需的变量
        int res=INT_MAX;//最小滑窗长度
        int st=0;//最小滑窗起点

        for (int i=0,j=0;i<n;i++) {//窗口指针i,j。顺序遍历字符串s
            if (num[s[i]]>0) cnt--;//所需字符数量-1
            num[s[i]]--;//对应计数数组-1
            if (cnt==0) {//窗口中包含所有所需字符
                while (j<i && num[s[j]]<0) {//窗口左指针右移(保证仍包含所有所需字符串)
                    num[s[j]]++;
                    j++;
                }//这样就得到了当前的最小窗口
                // res=min(res,i-j+1);//从0开始,故+1
                if (res>i-j+1) {//更新答案
                    res=i-j+1;
                    st=j;
                }
                num[s[j]]++;//左边界右移。令当前序列不合法。去找下一个合法序列
                j++;
                cnt++;
            }
        }
        return res==INT_MAX ? "" : s.substr(st,res);//substr截取字符串,左闭右开,参数为(起点,长度)
    }
};

### 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、付费专栏及课程。

余额充值