https://leetcode.cn/problems/minimum-window-substring/

一、个人版本

public class Solution1 {
    public String minWindow(String s, String t) {
        Balance balance = new Balance(s, t);
        Integer[] idxList = balance.idxList;
        if (idxList.length == 0 || idxList.length < t.length()) {
            return "";
        }
        if (t.length() == 1) {
            return t;
        }

        int rightSmallIdx = 0;
        int rightIdx = idxList[0];
        int leftSmallIdx = 0;
        int leftIdx = idxList[0];
        int minLeftIdx = leftIdx;
        int minRightIdx = s.length();


        do {
            if (balance.ok()) {
                // 左指针右移
                Character c = s.charAt(leftIdx);
                leftIdx = idxList[++leftSmallIdx];
                if (balance.removeAndOk(c) && rightIdx - leftIdx < minRightIdx - minLeftIdx) {
                    minLeftIdx = leftIdx;
                    minRightIdx = rightIdx;
                }
            } else {
                if (rightSmallIdx >= idxList.length) {
                    break;
                }
                // 右指针右移
                rightIdx = idxList[rightSmallIdx++];
                if (balance.addAndOk(s.charAt(rightIdx)) && rightIdx - leftIdx < minRightIdx - minLeftIdx) {
                    minLeftIdx = leftIdx;
                    minRightIdx = rightIdx;
                }
            }
        } while (true);
        if (minRightIdx == s.length()) {
            return "";
        }
        return s.substring(minLeftIdx, minRightIdx + 1);
    }

    public static class Balance {
        private int[] decrMap;
        private Integer needSize;
        private Integer[] idxList;

        public Balance(String s, String t) {
            // 构建counter
            int[] counter = new int[128];
            for (int i = 0; i < t.length(); i++) {
                counter[t.charAt(i)]++;
            }
            this.decrMap = counter;
            this.needSize = (int) Arrays.stream(counter).filter(e -> e > 0).count();
            this.idxList = IntStream.range(0, s.length()).boxed()
                .filter(i -> counter[s.charAt(i)] > 0).toArray(Integer[]::new);

        }

        public boolean ok() {
            return needSize <= 0;
        }

        private boolean addAndOk(Character c) {
            if (--decrMap[c] == 0) {
                --needSize;
            }
            return needSize <= 0;
        }

        public boolean removeAndOk(Character c) {
            if (++decrMap[c] == 1) {
                ++needSize;
            }
            return needSize <= 0;
        }
    }
}

二、最优版本

public class Solution2 {
    public String minWindow(String s, String t) {
        int[] cnt = new int[128];
        for (int i = 0; i < t.length(); i++) {
            cnt[t.charAt(i)]++;
        }
        int left = 0, right = 0, ansLeft = 0, ansRight = 0, ans = Integer.MAX_VALUE, moreT = t.length();
        while (right < s.length()) {
            // 右指针右移,无论是否命中,cnt[]--
            if (cnt[s.charAt(right++)]-- > 0) {
                moreT--;
            }

            // 满足时
            while (moreT == 0) {
                // 更新
                if (right - left < ans) {
                    ans = right - left;
                    ansLeft = left;
                    ansRight = right;
                }
                // 左指针右移, cnt[]++,绝杀,通过右指针的先行盈亏判断左指针是否需要计入
                if (cnt[s.charAt(left++)]++ == 0) {
                    moreT++;
                }
            }
        }
        return ans == Integer.MAX_VALUE ? "" : s.substring(ansLeft, ansRight);
    }
}

lindsay_bubble
26 声望11 粉丝