『题目』:
有一个只含有 'Q'
,'W'
, 'E'
, 'R'
四种字符,且长度为 n 的字符串。
假如在该字符串中,这四个字符都恰好出现 n/4
次,那么它就是一个「平衡字符串」。
给你一个这样的字符串s
,请通过「替换子串」的方式,使原字符串 s
变成一个「平衡字符串」。
你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。
请返回待替换子串的最小可能长度。
如果原字符串自身就是一个平衡字符串,则返回 0
。
『限制条件』:
1 <= s.length <= 10^5
s.length 是 4 的倍数
s 中只含有 'Q', 'W', 'E', 'R' 四种字符
『输入输出』
输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。
输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。
输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。
输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。
『题解』:
这道题目的意思是找一个子串
,只能对这个子串
的字母进行替换,然后使原串
变成平衡串
。
- 首先可以根据输入的
原串
的length
,得到每个字符pingjun=length/4
的个数 - 设
原串
的每个字符的个数为sums[i]
,我们知道要变的字符,肯定是那种比pingjun
要多的字符,那么就可以统计一下v[i]=sums[i]-pingjun >= 0 ? sums[i]-pingjun : 0
,这就是说,我们要找到一个子串的长度为len
,该长度能够包含v[i]
中的每个字符多出的个数。 - 这么就很好办了,我们可以从
len=(0,length)
,来二分枚举长度,因为明显,len
越大,所包含的字符肯定越多。如果当前len
的长度的所有子串
中,有包含v[i]
的每个字符的个数,len=(0,mid-1)
,继续枚举;如果没有包含,就len=(mid+1,len)
继续枚举。
『实现』:
public class test26 {
public boolean check(int[][] qianzhui,int[] sums,int len,int length)
{
for(int i = 0; i + len <= length;i++)
{
boolean flag = true;
for(int j = 0; j < 4 ;j++)
{
if(!(qianzhui[i + len][j] - qianzhui[i][j] >= sums[j]))
{
flag = false;
break;
}
}
if(flag) return true;
}
return false;
}
public int balancedString(String s) {
int len = 0;
if(s.length() % 4 != 0) return -1;
int length = s.length();
char[] cs = new char[length];
int [][] qianzhui = new int[length + 1][4];
int [] sums = new int[4];
s.getChars(0,length,cs,0);
for(int i = 0;i < 4;i++)
{
sums[i] = 0;
qianzhui[0][i] = 0;
}
for(int i = 0;i < length;i++)
{
for(int j = 0;j < 4;j++) qianzhui[i + 1][j] = qianzhui[i][j];
switch (cs[i])
{
case 'Q':
sums[0]++;
qianzhui[i + 1][0] ++;
break;
case 'W':
sums[1]++;
qianzhui[i + 1][1] ++;
break;
case 'E':
sums[2]++;
qianzhui[i + 1][2] ++;
break;
case 'R':
sums[3]++;
qianzhui[i + 1][3] ++;
break;
}
}
int pingjun = length / 4;
for(int i = 0;i < 4;i++)
{
if(sums[i] - pingjun >= 0)
{
sums[i] = sums[i] - pingjun;
len += sums[i];
}
else sums[i] = 0;
}
int left = len;
int right = s.length();
int mid;
int ans = right;
while(left <= right)
{
mid = (left + right) / 2;
if(check(qianzhui,sums,mid,length))
{
ans = mid;
right = mid - 1;
}
else left = mid + 1;
}
return ans;
}
public static void main(String[] args) {
test26 of = new test26();
String s = "QQQQ";
System.out.println(of.balancedString(s));
}
}