76. 最小覆盖子串 Java版

 博主主页: 码农派大星.

    数据结构专栏:Java数据结构

 数据库专栏:数据库

JavaEE专栏:JavaEE

软件测试专栏:软件测试

关注博主带你了解更多知识

Problem: 76. 最小覆盖子串

解析: 

先把 ss 和 tt 字符串转化为字符数组

char[] s = ss.toCharArray();

char[] t = tt.toCharArray();

再用数组模拟哈希表,统计各字符出现个数/频次, 为什么选数组模拟,而不是直接选用哈希表, 因为数组的时间复杂度为O(1), 哈希表时间复杂度虽然也是O(1),但是遇到哈希冲突时,时间复杂度就会变为O(n)

创建hash1数组 遍历 t数组字符出现个数/频次 , 并统计字符种类(kinds)

创建hash2数组 统计窗口中字符出现次数.频次

开始遍历 s数组 创建left right count 分别为0

进窗口前提:

char in = s[right] hash2[in]++

进窗口: 比较hash1和hash2字符是否相等, 如果相等种类 count ++

当 窗口hash2种类数 等于 hash1种类数时 说明此时窗口是一个可能覆盖的子串,但是我们要求的是最小子串

判断 如果 窗口长度 < minlen

则更新begin = left , minlen = right - left+1, 求包含所有t字符的最小窗口

出窗口前提: char out = s[left] ,left++

出窗口: if (hash2[out] == hash1[out]) count --

hash2[out]--

最后统计结果:

如果bengin 为起始-1 时 直接返回空串

否则 返回 begin位置 到 begin+minlen 位置字符串

复杂度分析:

代码: 

class Solution {
    public String minWindow(String ss, String tt) {


        char[] s = ss.toCharArray();
        char[] t = tt.toCharArray();
        if(ss.equals(tt)) return ss;

        int[] hash1 = new int[200]; //统计t字符出现的频次
        int kinds = 0;
        for(char ch : t){
            if(hash1[ch] == 0) kinds++;
            hash1[ch]++;
        }
        int[] hash2 = new int[200];//统计窗口中字符频次

        int minlen = Integer.MAX_VALUE, begin = -1;
        for(int left = 0, right = 0,count = 0; right < s.length; right++){

            char in = s[right];
            hash2[in]++;
             //进窗口+维护
            if(hash2[in] == hash1[in]) count++;
            while(kinds == count){//判断

                if(right - left+1 < minlen){//更新结果
                    begin = left;
                    minlen = right-left+1;
                }
                char out = s[left];
                left++;
                //出窗口+维护
                if(hash2[out] == hash1[out]) count--;
                hash2[out]--;

            }
        }
        if(begin == -1) return new String();
        else return ss.substring(begin,begin+minlen);

    }
}


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

余额充值