2026 年 7 月 11 日
本文解析LeetCode 1234题“替换子串得到平衡字符串”,解法基于滑动窗口。核心思路是:窗口外的字符频次不能超过目标频次(字符串长度/4),因为窗口内的子串可任意替换为所需字符,从而实现整体平衡。文章通过示例和反例说明该规律,并给出了check()判断函数和AC代码。
题目是这样说的:替换一段连续子串,使整个字符串变成平衡 。就是说: 这段连续子串可以删掉,然后填充新的字符,让整体平衡
原字符串
窗口里面:
XXXX
↓
替换以后
YYYY
如图,可以发现一个规律,就是窗口里面的字符串是什么,是否平衡并不重要。反正最后都会变成新的。也就是说,连续子串的这一段窗口都是待修改区域。
那么下意识就想到窗口内和窗口外的区别,这也是 滑动窗口 的一个规律,窗口内能随意修改吗?窗口外是否都不能改呢?
基本按照我们思维惯性可以往下面思考:
如果窗口外已经合法,那么窗口里面一定可以改成合法
所以来看看下面的这个例子

根据题意,我们可以得到这4个字符的出现频次只能是2次, A 字符多了一次,按照滑动窗口划分左右边界。我随意划分了2种,都是合法的
举一个反例

所以可以总结一个规律:
我们不妨将这个判断定义为 check()
可以定义伪代码
if(check()) l++;
class Solution {
public int balancedString(String s) {
int[] cnt = new int[4];
char[] chs = s.toCharArray();
for(char cur : chs){
cnt[index(cur)]++;
}
int validCount = 0;
int target = chs.length / 4;
for(int cur : cnt) if(cur == target) validCount++;
if(validCount == 4) return 0;
int l = 0;
int minlen = Integer.MAX_VALUE;
for(int r = 0; r < chs.length; r++){
cnt[index(chs[r])]--;
while(check(cnt, target)){
minlen = Math.min(minlen, r - l + 1);
cnt[index(chs[l])]++;
l++;
}
}
return minlen;
}
public boolean check(int[] cnt, int target){
for(int cur : cnt){
if(cur > target) return false;
}
return true;
}
public int index(char c){
if(c == 'Q') return 0;
if(c == 'W') return 1;
if(c == 'E') return 2;
if(c == 'R') return 3;
return -1;
}
}
正在加载评论...