LeetCode 1234. 替换子串得到平衡字符串 Replace the Substring for Balanced String - Java - 滑动窗口

36 篇文章 0 订阅
30 篇文章 1 订阅

一、替换子串得到平衡字符串

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

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

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

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

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

如果原字符串自身就是一个平衡字符串,则返回 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"@pfdvnah
示例5
输入:s = "WWEQERQWQWWRWWERQWEQ"
输出:4
解释:将 "WQWW" 替换成 "EQRR"
提示
  • 1 <= s.length <= 10^5
  • s.length4 的倍数
  • s 中只含有 'Q', 'W', 'E', 'R' 四种字符
隐藏提示
  • 使用 双指针算法 保证双指针外面的字符数量为 n / 4
  • 这意味着你需要计算每个字母的数量并确保数量足够

二、题解

这道题目属于 滑动窗口 类型的,也是 双指针 类型的题目。

用两个下标表示窗口左右边界,窗口里面就是我们要替换的字符串。由此可知,窗口外面的每种字符的数量必须小于平均值(s.length / 4)。否则无论怎么替换,外面都有字符超过数量。
因此要做的就是在保证外面的字符符合要求的前提下,使得窗口尽量小。

步骤:
先统计整个字符串中每种字符的数量。@pfdvnah
两个 int 型整数 leftright 表示窗口左右边界。窗口只能右移,不能左移。
窗口最初宽度为 1,在最左边。不断试探窗口左边界(即 left + 1),直到右边界抵达字符串末端。窗口不能移动为止。
别忘了记录窗口最小宽度,这个就是最终结果。

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)


三、Java代码

/***********************************************************************
原文链接:https://blog.csdn.net/pfdvnah/article/details/102671116
作者:wowpH
CSDN-ID:pfdvnah
***********************************************************************/
class Solution {
    public int balancedString(String s) {
        char[] arr = s.toCharArray();
        int len = arr.length;
		// 统计每种字符的数量。@pfdvnah
        int[] count = new int[26];
        for (int i = 0; i < len; ++i) {
            ++count[arr[i] - 'A'];
        }

        int left = 0, right = 0;
        int average = len / 4;// 字符的平均数量
        int ret = len;

        while (right < len) {// 窗口右边未出界
            --count[arr[right] - 'A'];// 字符从右边进入窗口,外面字符数量减1
            boolean flag = true;// 是否能向右移动窗口左边界即缩小窗口
            for (int i = 0; i < 26; ++i) {
                if (count[i] > average) {// 外面有字符的数量超过平均值
                    flag = false;// 窗口太小,不能缩小
                    break;
                }
            }
            while (true == flag && left < len) {// 可以缩小,并且未出界
                ++count[arr[left] - 'A'];// 字符从左边出窗口,数量减1
                ret = Math.min(ret, right - left + 1);// 更新结果
                if (count[arr[left] - 'A'] > average) {// 窗口外面字符数量超过平均值
                    flag = false;// 不能进一步缩小
                }
                ++left;// 窗口左边界右移,窗口缩小
            }
            ++right;// 窗口右边界右移,窗口增大
        }

        return ret;
    }
}

查看原文:https://blog.csdn.net/pfdvnah/article/details/102671116

- End - wowpH - pfdvnah -
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值