【滑动窗口】最小覆盖子串

求解代码

java 复制代码
    public String minWindow(String S, String T) {
        // 记录当前窗口中各字符的出现次数
        HashMap<Character, Integer> window = new HashMap<>();
        // 记录T中各字符需要的出现次数
        HashMap<Character, Integer> need = new HashMap<>();

        // 统计T中每个字符的出现次数
        for (char c : T.toCharArray()) {
            need.put(c, need.getOrDefault(c, 0) + 1);
        }

        int left = 0, right = 0; // 滑动窗口的左右指针,[left, right) 左闭右开区间
        int valid = 0; // 有效匹配数

        int start = 0, len = Integer.MAX_VALUE; // 记录最小窗口的起始下标和长度,初始len为无穷大

        // 右指针扩窗口 → 嵌套 左指针缩窗口
        while (right < S.length()) {
            char c = S.charAt(right); // 即将加入窗口的字符
            right++; // 右指针右移,扩大窗口(左闭右开,先取字符再移指针)

            // 若当前字符是T需要的字符,更新window表
            if (need.containsKey(c)) {
                window.put(c, window.getOrDefault(c, 0) + 1);
                // 当window中该字符的次数 == need中需要的次数时,有效匹配数+1
                if (window.get(c).equals(need.get(c))) {
                    valid++;
                }
            }

            // 当窗口满足条件(包含T所有字符),开始收缩左指针,找最小窗口
            while (valid == need.size()) {
                
                if (right - left < len) { // 若当前窗口长度更小,更新start和len
                    start = left; // 记录最小窗口的起始下标
                    len = right - left; // 记录最小窗口的长度(左闭右开,长度=right-left)
                }

                char d = S.charAt(left); // 即将移出窗口的字符
                left++; 

                // 若移出的字符是T需要的字符,更新window表和valid
                if (need.containsKey(d)) {
                    // 若移出前该字符的次数刚好满足need,移出后会不满足,有效匹配数-1
                    if (window.get(d).equals(need.get(d))) {
                        valid--;
                    }
                    window.put(d, window.get(d) - 1); // 窗口中该字符次数-1
                }
            }
        }

        // 若len仍为无穷大,说明无满足条件的窗口,返回空串;否则返回最小子串
        return len == Integer.MAX_VALUE ? "" : S.substring(start, start + len);
    }

小贴士

因为滑动窗口是左闭右开区间 ,所有len的计算不用+1。

相关推荐
sxlishaobin几秒前
Maven Setting详解
java·学习·maven
知守观6 分钟前
一个方法两个触发口:反编译 XXL-Job 后,我看清了 inner/job 子包的裸奔现状
java·spring boot·微服务
用户3126874877207 分钟前
CompletableFuture 链式编排:异步编程的优雅解法
java
瑞雪兆丰年兮23 分钟前
JavaWeb-day14-SpringBootWeb原理篇
java·开发语言·spring boot·spring·bean·mybatis·javaweb
神仙别闹35 分钟前
基于 Java GUI 贪心策略直接搜索算法和极大极小博弈树算法的智能人机博弈五子棋游戏
java·毕业设计·gui·贪心策略·极大极小博弈树
Flynn Liang2 小时前
RAG 评估体系:黄金集、检索指标与 LLM-as-Judge 落地
java·langchain·rag·评估·langchain4j·检索指标
SomeOtherTime2 小时前
Rust生命周期介绍(AI回答)
开发语言·后端·rust
程序猿打工仔2 小时前
计算机基础(C语言)考编、专技岗
c语言·开发语言·算法
喵本喵叁肆2 小时前
Rényi 差分隐私:把隐私损失看成一族矩(英文原题:Rényi Differential Privacy (CSF 2017))
开发语言·r语言
SimonKing3 小时前
Workbuddy太占C盘空间了,写个迁移工具迁走10G的数据
java·后端·程序员