一、Problem
有一个只含有 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符,且长度为 n 的字符串。
假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。
给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。
你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。
请返回待替换子串的最小可能长度。
如果原字符串自身就是一个平衡字符串,则返回 0。
输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。
提示:
1 <= s.length <= 10^5
s.length 是 4 的倍数
s 中只含有 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符
二、Solution
方法一:滑窗
- 窗口的含义
- 合法子串
- 窗口右边界右移时机
- 每次都右移
- 窗口左边界右移时机
- 窗口内部的字符都合法,这道题其实并不需要真的去替换字符,而是当一个子串从不合法变为合法时,一定是将某些多余的字符给隐式地替换了(
mp[c]--
),而给定的字符串的长度一定是 4 的倍数,所以保证可以替换成功。
- 窗口内部的字符都合法,这道题其实并不需要真的去替换字符,而是当一个子串从不合法变为合法时,一定是将某些多余的字符给隐式地替换了(
- 结算时机
- 左移前
class Solution {
boolean need(int[] mp, int tar) {
return mp['Q'] <= tar && mp['W'] <= tar && mp['E'] <= tar && mp['R'] <= tar;
}
public int balancedString(String S) {
int n = S.length(), tar = n >>> 2, l = 0, r = 0, ans = n+5, mp[] = new int[258];
char[] s = S.toCharArray();
for (char c : s)
mp[c]++;
while (r < n) {
mp[s[r]]--;
while (l < n && need(mp, tar)) {
mp[s[l]]++;
ans = Math.min(ans, r-l+1);
l++;
}
r++;
}
return ans;
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,