[每日一题]1234.替换子串得到平衡字符串
1234. 替换子串得到平衡字符串 有一个只含有 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符,且长度为 n 的字符串。假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。
给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。
请返回待替换子串的最小可能长度。
如果原字符串自身就是一个平衡字符串,则返回 0
输入:s = “QWER” 输出:0 解释:s 已经是平衡的了。
输入:s = “QQQW” 输出:2 解释:我们可以把前面的 “QQ” 替换成 “ER”。
Solution
class Solution {
public int balancedString(String s) {
//涉及到了子串问题,可以考虑使用滑动窗口
//当把窗口内包含的串作为被替换子串时,我们就需要保证窗口外的每个字符都是
//小于或者等于s长度的1/4.
//枚举所有的允许被替换的子串,并取出其中最短的长度作为返回值即可
int[] counts = new int[26];
int target = s.length()/4;
for(int i=0;i<s.length();i++){
counts[s.charAt(i)-'A']++;
}
//使用滑动窗口,左闭右开区间,所以区间长度为r-l
int res = s.length();//最长替换不会超过整个字符串长度
int l=0;
int r=0;
while(r<s.length()){
if(!isMatch(counts,target)){
//每次循环想窗口内扩充一个字符
//期望寻找一个可行解
//System.out.println("扩充窗口为:["+l+","+r+")");
counts[s.charAt(r)-'A']--;
r++;
}
//符合条件,则尝试增大l,以优化可被替换子串的长度
if(isMatch(counts,target)){
if(r==l){
//System.out.println("不用替换");
return 0;//不用替换,那就直接返回0即可
}else{
//不能以0返回,是一定能保证有超多出现的字母,所以窗口中至少有一个元素
//说明窗口内是有元素的,左端点的元素一定是有的:l<r
while(isMatch(counts,target)){
//System.out.println("找到一个符合条件的窗口:["+l+","+r+")");
res = Math.min(res,r-l);
counts[s.charAt(l)-'A']++;//放回窗口外
l++;
}
}
}
}
return res;
}
private boolean isMatch(int[] counts,int target){
return counts['Q'-'A']<=target&&
counts['W'-'A']<=target&&
counts['E'-'A']<=target&&
counts['R'-'A']<=target;
}
}