最小覆盖子串

76. 最小覆盖子串

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

示例:

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

说明:

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

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

public class T76 {

    public String minWindow(String s, String t) {
        if (s == null || t == null || s.length() == 0 || t.length() == 0 || t.length() > s.length()) {
            return "";
        }
        //初始化字母的个数
        Map<Character, Integer> needs = new HashMap<>();
        for (int i = 0; i < t.length(); i++) {
            char c = t.charAt(i);
            needs.put(c, needs.getOrDefault(c, 0) + 1);
        }

        //记录状态
        int left = 0,right = 0;
        int ans_left = 0, ans_right = -1, ans_len = Integer.MAX_VALUE;
        //遍历
        while (right < s.length()) {
            //判断right处是否是需要的字符
            char r = s.charAt(right);
            if (needs.containsKey(r)) {
                needs.put(r, needs.get(r) - 1);
                //当前窗口包含左右字符——needs里的value均为0
                while (match(needs)) {
                    int cur_len = right - left + 1;
                    if (cur_len < ans_len) {
                        ans_len = cur_len;
                        ans_left = left;
                        ans_right = right;
                    }
                    char l = s.charAt(left);
                    if (needs.containsKey(l)) {
                        needs.put(l, needs.get(l) + 1);
                    }
                    left++;
                }

            }
            //增加右指针
            right++;
        }

        return s.substring(ans_left, ans_right + 1);

    }

    private boolean match(Map<Character, Integer> needs) {
        for (Integer num : needs.values()) {
            if (num > 0) {
                return false;
            }
        }
        return true;
    }
}

 

posted @ 2020-03-19 15:10  海绵爱上星  阅读(143)  评论(0编辑  收藏  举报