开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情
1234. 替换子串得到平衡字符串
有一个只含有 'Q', 'W', 'E', 'R' 四种字符,且长度为 n 的字符串。
假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。
给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。
你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。
请返回待替换子串的最小可能长度。
如果原字符串自身就是一个平衡字符串,则返回 0。
示例 1:
输入: s = "QWER"
输出: 0
解释: s 已经是平衡的了。
示例 2:
输入: s = "QQWE"
输出: 1
解释: 我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。
提示:
1 <= s.length <= 10^5s.length是4的倍数s中只含有'Q','W','E','R'四种字符
思路
我们首先要做到的是找到那些超过 n / 4 次的字符,新的子字符串会代替原字符串,我们要求的是子字符串的长度,故对于未超过 n / 4 的字符不需要考虑。
对于子字符串来说,我们肯定是需要遍历得到的,对于所求子字符串的长度,我们只需要找到除了那些字符串后,我们的其余字符次数是不超过 n / 4 的。对于这类问题,我们可以通过滑动窗口的方式解决。
右边界负责将字符次数减一,表示移除该字符,左边界负责将字符次数加一,表示还原该字符,当当前剩余字符的次数符合要求时,我们才可以进行左边界的右移,同时,我们也可以将子字符串的长度记录下来,以比较获得最短子字符串的长度。
题解
class Solution {
public int balancedString(String s) {
int n = s.length();
Map<Character, Integer> map = new HashMap<>();
for(int i = 0; i < n; i++) {
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);
}
if(check(map, n / 4)) {
return 0;
}
int ans = Integer.MAX_VALUE;
for(int i = 0, j = 0; j < n; j++) {
map.put(s.charAt(j), map.get(s.charAt(j)) - 1);
while(i <= j && check(map, n / 4)) {
ans = Math.min(ans, j - i + 1);
map.put(s.charAt(i), map.get(s.charAt(i)) + 1);
i++;
}
}
return ans;
}
private boolean check(Map<Character, Integer> map, int size) {
for(Map.Entry<Character, Integer> entry: map.entrySet()) {
if(entry.getValue() > size) {
return false;
}
}
return true;
}
}
如果你有其他的思路或者更好的解法,亦或者你发现了文章出现了错误或有不足,欢迎在评论区和我交流,我看到了一定会回复。
写文章不易,如果你觉得文章对你有帮助,麻烦点一下点赞、收藏,你的支持是我写文章的最大动力!