zoukankan      html  css  js  c++  java
  • [LeetCode 1234] Replace the Substring for Balanced String

    You are given a string containing only 4 kinds of characters 'Q', 'W', 'E' and 'R'.

    A string is said to be balanced if each of its characters appears n/4 times where n is the length of the string.

    Return the minimum length of the substring that can be replaced with any other string of the same length to make the original string s balanced.

    Return 0 if the string is already balanced.

    Example 1:

    Input: s = "QWER"
    Output: 0
    Explanation: s is already balanced.

    Example 2:

    Input: s = "QQWE"
    Output: 1
    Explanation: We need to replace a 'Q' to 'R', so that "RQWE" (or "QRWE") is balanced.
    

    Example 3:

    Input: s = "QQQW"
    Output: 2
    Explanation: We can replace the first "QQ" to "ER". 
    

    Example 4:

    Input: s = "QQQQ"
    Output: 3
    Explanation: We can replace the last 3 'Q' to make s = "QWER".
    

    Constraints:

    • 1 <= s.length <= 10^5
    • s.length is a multiple of 4
    • contains only 'Q''W''E' and 'R'.

    Solution 1. Binary Search on the final answer. O(N * log N) runtime, N is the input string's length

    1. Do a linear scan to get all 4 letters' counts. Subtract each letter's count by s.length() / 4. This represents for each letter, how many letters are redundant (count - s.length() / 4 > 0) or missing(count - s.length() / 4 < 0). 

    2. The minimum window must be in range [0, s.length()]. Binary search on this range, for each window length WL that needs to be checked, do the following.

    From left to right, check each winodw of length WL can make s balanced. If true, search on the left half, including WL; If false, search on the right half, excluding WL. This is correct because if a winow of length WL can not make s balanced, then all windows of smaller length can not make s balanced either. The answer must be in the right half of the search range. 

    Each check on a certain window length takes O(N) time. Each time a character slides out, we add 1 to the according count because there is 1 fewer character to reduce the difference against s.length() / 4. Each time a character slides in, we subtract the according count by 1 because there is 1 more character to reduce the difference against s.length() / 4.

    When all 4 difference count are <= 0, the current window size makes s balanced. 

     Proof:  As long as there is at least 1 difference count of letter c that is > 0, we know that the maximum c we can get rid of inside the current window is not enough. Because the total characters' count is fixed, if we can get rid of all redundant letters inside a window, we can also add all required missing letters to make s balanced. The key here is that for a given window and letter counts that is > s.length() / 4, we can only get rid of at most K redundant letter for each count, K is the count of such a letter inside the current sliding window.

    class Solution {
        private Map<Character, Integer> idxMap = new HashMap<>();
        public int balancedString(String s) {
            idxMap.put('Q', 0); idxMap.put('W', 1); idxMap.put('E', 2); idxMap.put('R', 3);
            int[] cnt = new int[4];
            for(int i = 0; i < s.length(); i++) {
                cnt[idxMap.get(s.charAt(i))]++;
            }
            for(int i = 0; i < cnt.length; i++) {
                cnt[i] -= (s.length() / 4);
            }
            int left = 0, right = s.length();
            while(left < right - 1) {
                int mid = left + (right - left) / 2;
                int[] cntCopy = Arrays.copyOf(cnt, cnt.length);
                if(check(s, cntCopy, mid)) {
                    right = mid;
                }
                else {
                    left = mid + 1;
                }
            }
            int[] cntCopy = Arrays.copyOf(cnt, cnt.length);
            if(check(s, cntCopy, left)) {
                return left;
            }
            return right;
        }
        private boolean check(String s, int[] cnt, int window) {
            for(int i = 0; i < window; i++) {
                cnt[idxMap.get(s.charAt(i))]--;
            }
            if(cnt[0] <= 0 && cnt[1] <= 0 && cnt[2] <= 0 && cnt[3] <= 0) {
                return true;
            }
            for(int i = window; i < s.length(); i++) {
                cnt[idxMap.get(s.charAt(i - window))]++;
                cnt[idxMap.get(s.charAt(i))]--;
                if(cnt[0] <= 0 && cnt[1] <= 0 && cnt[2] <= 0 && cnt[3] <= 0) {
                    return true;
                }          
            }
            return false;
        }
    }

    Solution 2. Sliding window + two pointers, O(N) runtime.

    Similarly with solution 1, except instead of a binary search on the final answer, use a left and right pointers to represent the minimum length window that can make s balanced. 

    1. as long as s is not balanced, keep moving r to the right;

    2. as soons as s is balanced, keep moving l to the right until s is not balanced anymore.

    3. update res as Math.min(res, r - l + 1) then repeat these 3 steps until r is out of bound.

    class Solution {
        public int balancedString(String s) {
            Map<Character, Integer> idxMap = new HashMap<>();
            idxMap.put('Q', 0); idxMap.put('W', 1); idxMap.put('E', 2); idxMap.put('R', 3);
            int[] cnt = new int[4];
            Arrays.fill(cnt, -s.length() / 4);
            
            for(int i = 0; i < s.length(); i++) {
                cnt[idxMap.get(s.charAt(i))]++;
            }
            
            if(cnt[0] == 0 && cnt[1] == 0 && cnt[2] == 0 && cnt[3] == 0) {
                return 0;
            }
            
            int l = 0, r = 0, res = s.length();
            while(r < s.length()) {
                while(r < s.length() && (cnt[0] > 0 || cnt[1] > 0 || cnt[2] > 0 || cnt[3] > 0)) {
                    cnt[idxMap.get(s.charAt(r))]--;
                    r++;
                }
                //no need to check if l is out of bound, because we already exclude the answer 0 case;
                //after l is incremented to s.length(), cnt[0] <= 0 && cnt[1] <= 0 && cnt[2] <= 0 && cnt[3] <= 0
                //is always false.
                while(l <= r && cnt[0] <= 0 && cnt[1] <= 0 && cnt[2] <= 0 && cnt[3] <= 0) {
                    cnt[idxMap.get(s.charAt(l))]++;
                    l++;
                }
                res = Math.min(res, r - l + 1);
            }
            return res;
        }
    }
  • 相关阅读:
    高等代数中的名词解析No1
    概率论中的名词解释(个人理解,非官方) No1
    概率论中的公式解释(个人理解,非官方) No1
    CentOS7 网络设置
    神经网络与人工智能No0导言(笔记版)
    centos7 防火墙设置
    神经网络与人工智能No1Rosenblatt感知器(笔记版)
    输入法打不出来的数学符号大全
    php对xml文件的解析
    PHPExcel生成Excel模版
  • 原文地址:https://www.cnblogs.com/lz87/p/11711860.html
Copyright © 2011-2022 走看看