LeetCode 1234. 替换子串得到平衡字符串

给定一个只含Q,W,E,R字符的字符串,通过最小长度的子串替换使其成为平衡字符串。使用滑动窗口策略找出满足条件的子串长度,如果原字符串已是平衡,则返回0。
摘要由CSDN通过智能技术生成

1234. 替换子串得到平衡字符串

有一个只含有 'Q', 'W', 'E', 'R' 四种字符,且长度为 n 的字符串。

假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。

给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。

你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。

请返回待替换子串的最小可能长度。

如果原字符串自身就是一个平衡字符串,则返回 0

示例 1:

输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。

示例 2:

输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。

示例 3:

输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。 

示例 4:

输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。

提示:

  • 1 <= s.length <= 10^5
  • s.length 是 4 的倍数
  • s 中只含有 'Q''W''E''R' 四种字符

提示 1

Use 2-pointers algorithm to make sure all amount of characters outside the 2 pointers are smaller or equal to n/4.


提示 2

That means you need to count the amount of each letter and make sure the amount is enough.

 

解法:滑动窗口 

 
题目的要求是找到一个「待替换子串」,通过替换这个子串,使得原字符串s变成一个「平衡字符串」。
也就是说原字符串可以看作两个部分:「待替换子串」 + 「不替换的内容」

根据题意,如果在待替换子串之外的任意字符的出现次数超过 m = n / 4 ,那么无论怎么替换,都无法使这个字符在整个字符串中的出现次数为 m。

也就是说,如果在待替换子串之外的任意字符的出现次数都不超过 m,那么可以通过替换,使 s 为平衡字符串,即每个字符的出现次数均为 m。

因此我们的目标就是,找到最短的「待替换子串」,使得「不替换的内容」中四个字符的出现次数小于等于m。

那么如何去搜索最短的「待替换子串」?

当「不替换的内容」(窗口外的串)中四个字符的出现次数小于等于 m 时,此时「待替换子串」(窗口内的子串)为合法子串。

  • 如果当前得到的子串是一个合法子串,那么left右移缩短字符串;如果left已经到达字符串尾部,说明没有缩小的空间,那么就结束搜索。
  • 如果当前得到的子串不是合法子串,right右移延伸字符串;如果right已经到达字符串尾部,说明没有延伸的空间,那么就结束搜索。

因为我们在搜索过程中要时刻判断 (窗口外的串) 中四个字符的出现次数是否小于等于 m ,因此我们必须先遍历一遍整个字符串,得到字符的总共出现次数,然后在滑动窗口的移动过程中,动态的增加或减少对应字符出现的次数,来维护(窗口外的串)中四个字符的出现次数。

class Solution {
    public int balancedString(String s) {
        int n = s.length();
        int m = n / 4;
        // 存储窗口外的四种字符各自的数量
        int[] windowOut = new int[4];
        for (int i = 0; i < n; i++) {
            switch (s.charAt(i)) {
                case 'Q':
                    windowOut[0]++;
                    break;
                case 'W':
                    windowOut[1]++;
                    break;
                case 'E':
                    windowOut[2]++;
                    break;
                case 'R':
                    windowOut[3]++;
                    break;
            }
        }
        // 窗口外的四种字符各自的数量都恰好等于m,它已经是一个「平衡字符串」了
        if (windowOut[0] == m && windowOut[1] == m && windowOut[2] == m && windowOut[3] == m) {
            return 0;
        }
        int ans = Integer.MAX_VALUE;
        int left = 0;
        int right = 0;
        while (right < n) {
            char c = s.charAt(right);
            switch (c) {
                case 'Q':
                    windowOut[0]--;
                    break;
                case 'W':
                    windowOut[1]--;
                    break;
                case 'E':
                    windowOut[2]--;
                    break;
                case 'R':
                    windowOut[3]--;
                    break;
            }

            // 窗口外的任何一种字符数量都不超过m,此时窗口内子串(代替换子串)合法,尝试收缩左边界
            while (windowOut[0] <= m && windowOut[1] <= m && windowOut[2] <= m && windowOut[3] <= m) {
                ans = Math.min(ans, right - left + 1);
                char delete = s.charAt(left);
                left++;
                switch (delete) {
                    case 'Q':
                        windowOut[0]++;
                        break;
                    case 'W':
                        windowOut[1]++;
                        break;
                    case 'E':
                        windowOut[2]++;
                        break;
                    case 'R':
                        windowOut[3]++;
                        break;
                }
            }

            // 窗口外的任何一种字符数量超过m,此时窗口内子串(代替换子串)不合法,扩大右边界
            right++;
        }
        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(n),n 是 字符串 s 的长度。
  • 空间复杂度:O(1)。 
  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值