最小覆盖子串

题目链接:最小覆盖子串

题目描述:
给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。

示例:

输入:S = “ADOBECODEBANC”, T = “ABC”
输出:“BANC”

提示:

如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。

题目分析:双指针加滑动窗口。在S中用i ,j 维护一个滑动窗口,j不断向右延申,一旦窗口中的值包含T中所有字符时,我们就开始收缩左边界i,直到窗口中的值不再包含T的所有字符,在收缩i的过程中同时不断更新ans。那么我们如何判断窗口是否包含T的所有字符呢?方法是使用Map计数,对每个字符出现的次数计数,注意这里不能直接用set去做判断,因为T中一个字符可能出现多次。用一个变量cnt,当窗口中的值为T包含字符时,cnt++,因此当cnt == T.length时,此时就包含了T所有字符,然后开始收缩指针i,收缩时如果碰到T中包含的字符,同时要将cnt–,这样才能保证窗口中的值包含T中字符的个数是准确的。看代码吧。

代码:

class Solution {
    public String minWindow(String s, String t) {
        int[] windows = new int[129];
        int[] need = new int[129];
        char[] tt = t.toCharArray();
        char[] ss = s.toCharArray();
        for(int i = 0;i < tt.length;i++) need[tt[i]]++;
        int i = 0, j = 0,min = s.length(),cnt = 0;
        String ans = "";
        while(j < ss.length){
            char c = ss[j];
            windows[c]++;
            if(windows[c]<=need[c]) cnt++;
            while(cnt == tt.length){//包含T全部了,开始收缩
                if(j-i+1<=min){
                    min = j-i+1;
                    ans = s.substring(i,j+1);
                }
                windows[ss[i]]--;
                if(windows[ss[i]]<need[ss[i]]) cnt--;//维持窗口中T的字符出现次数
                i++;
                if(i>=ss.length) break;
            }
            j++;
        }

       return ans;
    }
}


变式:求解一个字符串S的包含它自身所有字符的最短子串。
分析:完全就是上面的思路,只需要先利用set先求出S的所有字符组成的字符串,即T,然后套着上题就行了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值