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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/pfdvnah/article/details/102671116

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

有一个只含有 '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 ( 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 -

猜你喜欢

转载自blog.csdn.net/pfdvnah/article/details/102671116