有一个只含有 'Q'
, 'W'
, 'E'
, 'R'
四种字符,且长度为 n
的字符串。
假如在该字符串中,这四个字符都恰好出现 n/4
次,那么它就是一个「平衡字符串」。
给你一个这样的字符串 s
,请通过「替换子串」的方式,使原字符串 s
变成一个「平衡字符串」。
你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。
请返回待替换子串 @wowpH 的最小可能长度。
如果原字符串自身就是一个平衡字符串,则返回 0
。
输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。
输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。
输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。
输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。
@pfdvnah
输入:s = "WWEQERQWQWWRWWERQWEQ"
输出:4
解释:将 "WQWW" 替换成 "EQRR"。
1 <= s.length <= 10^5
s.length
是 4
的倍数s
中只含有 'Q'
, 'W'
, 'E'
, 'R'
四种字符n / 4
这道题目属于 滑动窗口 类型的,也是 双指针 类型的题目。
用两个下标表示窗口左右边界,窗口里面就是我们要替换的字符串。由此可知,窗口外面的每种字符的数量必须小于平均值(s.length / 4
)。否则无论怎么替换,外面都有字符超过数量。
因此要做的就是在保证外面的字符符合要求的前提下,使得窗口尽量小。
步骤:
先统计整个字符串中每种字符的数量。@pfdvnah
两个 int
型整数 left
和 right
表示窗口左右边界。窗口只能右移,不能左移。
窗口最初宽度为 1
,在最左边。不断试探窗口左边界(即 left + 1
),直到右边界抵达字符串末端。窗口不能移动为止。
别忘了记录窗口最小宽度,这个就是最终结果。
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
/***********************************************************************
原文链接: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