每日一题——最小覆盖子串

菜鸡每日一题系列打卡76

每天一道算法题目 

小伙伴们一起留言打卡

坚持就是胜利,我们一起努力!

题目描述(引自LeetCode)

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

示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

说明:

  • 如果S中不存这样的子串,则返回空字符串""。

  • 如果S中存在这样的子串,我们保证它是唯一的答案。

题目分析

本题是一道寻找字符串符合要求的子串的题目。容易想到的是,先在S中找到包含T所有字符的子串,然后再找到最小子串。这一过程可以利用滑动窗口进行实现。

经过在LeetCode平台的一番测试之后,菜鸡发现了两个现象:

  • T中的字符有可能重复

  • 测试用例中S与T均由大小写字母组成

这两点很关键,菜鸡将以这两点为前提,进行解答。

代码实现

class Solution {


    public String minWindow(String s, String t) {
        // 特殊情况判断
        if (s == null || t == null || s.length() < t.length()) return "";
        // 准备
        int start = 0, end = 0, count = 0;
        int minStart = -1, minEnd = -1, minLength = s.length() + 1;
        int[] tArray = new int[58], tmp = new int[58];
        for (int i = 0; i < t.length(); i++) tArray[t.charAt(i) - 65]++;
        // 滑动窗口
        while (end < s.length()) {
            int index = s.charAt(end) - 65;
            if (tArray[index] >= ++tmp[index]) count++;
            while (count == t.length()) {
                index = s.charAt(start) - 65;
                if (tArray[index] >= tmp[index]--) {
                    count--;
                    if (end - start + 1 < minLength) {
                        minLength = end - start + 1;
                        minStart = start;
                        minEnd = end;
                    }
                }
                start++;
            }
            end++;
        }
        // 返回结果
        return minStart == -1 ? "" : s.substring(minStart, minEnd + 1);
    }


}

代码分析

再次强调,本解答是基于S与T均由大小写字母组成的前提下实现的,如果字符集有变化,则需要相应地增大数组长度,也可以用map进行实现。

对代码进行分析,不妨设S长度为m,T长度为n,字符集大小为c,则时间复杂度为O(cm + n)。一般情况下,n < m,c可以认为是某种程度的常数,因此,时间复杂度可以看作O(m)。

而就空间而言,空间复杂度为O(c),c可以认为是某种程度的常数,因此,空间复杂度可以看作O(1)。

执行结果

学习 | 工作 | 分享

????长按关注“有理想的菜鸡

只有你想不到,没有你学不到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值