LeetCode76:最小覆盖子串

题目描述

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

示例:

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

说明:

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

package dongtaiguihua;

public class DT_76_Demo {

    public static void main(String[] args) {
        DT_76_Demo dt = new DT_76_Demo();
        String s = "DAOBECODEBANC";
        String t = "ABC";
        String str = dt.minWindow(s,t);
        System.out.println(str);
    }
/*
    public String minWindow(String s, String t) {

        //代表字符
        int[] map = new int[128];
        //现在这个map<(A,1), (B,1), (C,1)>
        for (char c : t.toCharArray()) map[c]++;

        int count = t.length();
        int begin = 0;
        int end = 0;
        int d = Integer.MAX_VALUE;
        int head = 0;

        while (end < s.length()) {
            if (map[s.charAt(end++)]-- > 0) count--;
            while (count == 0) {
                //1.恰好是包含的子串,更新子串.
                if (end - begin < d) {
                    d = end - begin;
                    head = begin;
                }
                //2.不包含子串,那么继续走,寻找下一个可能包含的.
                if (map[s.charAt(begin)] == 0)
                    count++;
                //System.out.println("s.charAt(begin) = " + s.charAt(begin));
                map[s.charAt(begin)]++;
                begin++;
            }
        }
        //返回字串
        return d == Integer.MAX_VALUE ? "" : s.substring(head, head + d);
        */


    public String minWindow(String s, String t) {
        int[] srcHash = new int[255];
        // 记录目标字符串每个字母出现次数
        for(int i = 0; i < t.length(); i++){
            srcHash[t.charAt(i)]++;
        }
        int start = 0,i= 0;
        // 用于记录窗口内每个字母出现次数
        int[] destHash = new int[255];
        int found = 0;
        int begin = -1, end = s.length(), minLength = s.length();
        
        for(start = i = 0; i < s.length(); i++){
            // 每来一个字符给它的出现次数加1
            destHash[s.charAt(i)]++;
            // 如果加1后这个字符的数量不超过目标串中该字符的数量,则找到了一个匹配字符
            if(destHash[s.charAt(i)] <= srcHash[s.charAt(i)]) found++;
            // 如果找到的匹配字符数等于目标串长度,说明找到了一个符合要求的子串
            if(found == t.length()){
                // 将开头没用的都跳过,没用是指该字符出现次数超过了目标串中出现的次数,并把它们出现次数都减1
                while(start < i && destHash[s.charAt(start)] > srcHash[s.charAt(start)]){
                    destHash[s.charAt(start)]--;
                    start++;
                }
                // 这时候start指向该子串开头的字母,判断该子串长度
                if(i - start < minLength){
                    minLength = i - start;
                    begin = start;
                    end = i;
                }
                // 把开头的这个匹配字符跳过,并将匹配字符数减1
                destHash[s.charAt(start)]--;
                found--;
                // 子串起始位置加1,我们开始看下一个子串了
                start++;
            }
        }
        // 如果begin没有修改过,返回空
        return begin == -1 ? "" : s.substring(begin,end + 1);
    }
}
参考连接

https://www.jianshu.com/p/ce80b4c07c22

你可能感兴趣的:(LeetCode76:最小覆盖子串)