Minimum Window Substring 最小窗口子串

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".

Note:
If there is no such window in S that covers all characters in T, return the empty string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

这道题目的思路跟 找到链接所有单词的子串有些类似,我们容易得到一个时间复杂度为O( n^2 )的解法。

我们用start和end来标记子串的开始和结束,每次从start index = 0开始,找到合法的子字符串。

但我们要意识到:

如果S = "aabc", T = "abc"

当start = 0 的时候,我们可以得到end = 3,此时的子串长度为4

当start = 1的是时候,其实我们没有必要再次进行计算了,start = 1也是符合要求的子串。

所以,我们的思路转变成了:

1. 从start开始,先找到一个合法的子串

2. 在这个子串中寻找有没有更小的子串

这样可以避免大量重复的计算。

再以S = "ebadbaccb", T = "abc"为例。

当start = 0的时候,我们可以得到end = 6。我们得到了一个合法的子串。

之后寻找更小的子串,对于不在"abc"中 (比如s [ 0 ] ) 和多余的字符(比如s [ 2 ] ), 我们都可以舍弃掉,最后start = 4。我们得到了当前最小的length = 3的子串。

之后start ++ , end还是在6,此时"b"是缺省的,继续往后找,有可以得到end = 8, start = 5, 此时的子串长度为5。

所以,最小的长度为3。

算法的时间复杂度为O ( n )。

运行时间:


代码:

public class MinimumWindowSubstring {

    public String minWindow(String s, String t) {
        int[] count = new int[128];
        for (int i = 0; i < t.length(); i++) {
            count[t.charAt(i)]++;
        }
        int start = 0, i = 0, countNum = t.length();
        int minBegin = -1;
        int minLen = Integer.MAX_VALUE;
        while (i < s.length() - countNum + 1) {
            if (count[s.charAt(i)] > 0) {
                countNum--;
            }
            count[s.charAt(i)]--;
            i++;
            while (countNum == 0) { // avoid some repeat
                if (i - start < minLen) {
                    minLen = i - start;
                    minBegin = start;
                }
                count[s.charAt(start)]++;
                // when char exists in t, increase counter.
                if (count[s.charAt(start)] > 0) {
                    countNum++;
                }
                start++;
            }
        }
        return minBegin == -1 ? "" : s.substring(minBegin, minBegin + minLen);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值