最小子串覆盖 · Minimum Window Substring

本文详细解析了如何在源字符串中找到包含目标字符串所有字符的最小子串,通过使用大小为256的数组作为hashmap记录目标字符串中各字符的出现次数,实现了高效的搜索算法。

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

/**
 * Description:
 * 描述
 * 给定一个字符串source和一个目标字符串target,在字符串source中找到包括所有目标字符串字母的子串。
 * <p>
 * 如果在source中没有这样的子串,返回"",如果有多个这样的子串,返回起始位置最小的子串。
 * <p>
 * 说明
 * 在答案的子串中的字母在目标字符串中是否需要具有相同的顺序?
 * <p>
 * ——不需要。
 * <p>
 * 样例
 * 给出source = "ADOBECODEBANC",target = "ABC" 满足要求的解  "BANC"
 * <p>
 * <p>
 * 题目:找到包含target串中所有字符的最小字串。
 * <p>
 * 思路:
 * <p>
 * 首先采用一个大小为256的数组充当hashmap的功能,记录tartget中字母出现次数。
 * 算法流程如下: 
 * <p>
 * 1. 先将target中所有的字符出现的次数保存到td数组中。
 * 2. 遍历source数组,开始时start=0,i=0;
 * <p>
 *    start记录当前字串的起点,i相当于当前字串的终点。
 * <p>
 *     用found表示当前字串中包含target中字符的数目,如果found=target.length()则表明当前字串包含了target中所有字符,如果满足,进入下一步。
 * <p>
 * 3. 将start后移,取出start前面多余的元素,已达到字串最小的目标。
 * <p>
 * 4.判断,如果当前字串小于历史搜到的最小字串,则将当前字串的长度,起始点,结束点都记录,更新。
 * <p>
 * 5.将start后移,寻找下一个字串。
 * ---------------------
 * 作者:cosmos_lee
 * 来源:优快云
 * 原文:https://blog.youkuaiyun.com/u012156116/article/details/80648698
 * 版权声明:本文为博主原创文章,转载请附上博文链接!
 */
public class MixWindow {
    public static String minWindow(String source, String target) {
        // write your code here
        if (Strings.isNullOrEmpty(source) || Strings.isNullOrEmpty(target)) {
            return "";
        }

        char[] td = new char[256];
        for (char tc : target.toCharArray()) {
            td[tc]++;
        }
        char[] sd = new char[256];
        int minLen = source.length();
        int start = 0;
        int first = -1, end = 0;
        int found = 0;  // 在source中发现了target中元素的数目
        for (int i = 0; i < source.length(); i++) {
            sd[source.charAt(i)]++;
            if (sd[source.charAt(i)] <= td[source.charAt(i)]) {
                found++;
            }
            if (found == target.length()) {
                // 满足条件
                // 处理1:start后移,删除无用元素
                while (start <= i && sd[source.charAt(start)] > td[source.charAt(start)]) {
                    sd[source.charAt(start)]--;
                    start++;
                }
                // 处理2:如果比当前最小子串小,则更新
                if (i + 1 - start <= minLen) {
                    minLen = i + 1 - start;
                    first = start;
                    end = i + 1;
                }
                sd[source.charAt(start)]--;
                start++;
                found--;
            }
        }
        if (first == -1) {
            return "";
        } else {
            return source.substring(first, end);
        }
    }
}

https://blog.youkuaiyun.com/u012156116/article/details/80648698

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值