Leetcode 76. 最小覆盖子串

本文介绍了一种使用滑动窗口算法解决字符串匹配问题的方法,并通过一个具体示例详细展示了如何找到包含目标字符串所有字符的最短子串。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。

示例:

输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”

说明:

  • 如果 S 中不存这样的子串,则返回空字符串 “”。
  • 如果 S 中存在这样的子串,我们保证它是唯一的答案。

解答

使用滑动窗口算法思想。

滑动窗口问题通用模板如下(本文章的重点内容!)
int left = 0, right = 0;

while (right < s.size()) {
    window.add(s[right]);
    right++;
    
    while (valid) {
        window.remove(s[left]);
        left++;
    }
}

本题步骤如下

  1. 先将 t 字符串的所有字符存入哈希表。
  2. 声明 lt, gt 两个指针作为滑动窗口 [lt, gt - 1] 的边界
  3. 此时如果窗口还不能匹配 t 的窗口, 让窗口扩大,gt ++ 。
  4. 若能匹配 t 的窗口, 统计最小子串,然后使窗口缩小,不断地让左边界 lt ++ ,直到不再覆盖 t 字串。

tips:本题优化成 int[128] 代替 哈希表 效率会很高,但不太通用,我认为此优化学习不到啥,所以我没做。

复杂度:O(S + T) 时间,O(S + T) 空间。

本题代码
class Solution {
    public String minWindow(String s, String t) {
        char[] ts = t.toCharArray();
        Map<Character, Integer> needs = new HashMap<>();
        for(char ch : ts) needs.put(ch, needs.getOrDefault(ch, 0) + 1);
        
        Map<Character, Integer> window = new HashMap<>();
        int lt = 0; int gt = 0;
        int start = 0; int end = s.length() + 1;
        int match = 0;
        while(gt < s.length()) {
            char c1 = s.charAt(gt);
            if(needs.containsKey(c1)) {
                window.put(c1, window.getOrDefault(c1, 0) + 1);
                if(window.get(c1).equals(needs.get(c1))) match ++;
            }
            
            gt ++;
            
            while(match == needs.size()) {
                if(gt - lt < end - start) {
                    start = lt;
                    end = gt;
                }
                
                char c2 = s.charAt(lt);
                if(needs.containsKey(c2)) {
                    window.put(c2, window.get(c2) - 1);
                    if(window.get(c2) < needs.get(c2)) match --;
                }
                
                lt ++;
            }
        }
            
        return end == s.length() + 1 ? "" : s.substring(start, end);
    }
}
结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值