题目:
一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?如果 s 已经平衡则输出0。
Input:
一行字符表示给定的字符串s。
Output:
一个整数表示答案。
Examples:
Input :
QWER
Output :
0
Input :
QQWE
Output :
1
Input :
QQQW
Output :
2
Input :
QQQQ
Output :
3
Note:
1<=n<=10^5。n是4的倍数。字符串中仅包含字符 ‘Q’, ‘W’, ‘E’ 和 ‘R’。
题目分析:
-
因为所求解答案为一个连续区间 且区间左右端点移动有明确方向 满足尺取法的使用情况。
-
• 先用数组num计算出字符串中 ‘Q’, ‘W’, ‘E’ 和 'R’出现的总次数;当每个字符出现的次数相等且刚好等于n/4的时候,已经平衡,输出0。
• 否则的话,更新num[0], num[1], num[2], num[3] 分别记录不包含区间 [l, r] 这一段时,字符 ‘Q’, ‘W’, ‘E’ 和 ‘R’ 的个数 。
• 先通过替换使 4 类字符数量一致,int total=r-l+1;total-=(maxx-num[0])+(maxx-num[1])+(maxx-num[2])+(maxx-num[3]);
•再判断剩余空闲位置是否 为 4 的倍数 • 若 total ≥0 且为 4 的倍数,则满足要求;更新num数组,继续寻找更小的区间,l++。
• 否则当前 [l,r] 不满足要求,则更新num数组, r++,扩大区间范围继续尺取寻找。
(错选了language为Microsoft Visual C++ 2010导致ce了,还傻乎乎找了好久的错,language应该是GNU G++17 7.3.0才对)
代码:
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
string s;
cin>>s;
int len=s.length();
int ans=len+1;
int l=0,r=0;
int m=len/4;//平衡的话每个字符个数
int num[4];
memset(num,0,sizeof(num));
for(int i=0;i<len;i++)//记录每个字符在字符串中出现次数
{
if(s[i]=='Q')
{
num[0]++;
}
else if(s[i]=='W')
{
num[1]++;
}
else if(s[i]=='E')
{
num[2]++;
}
else if(s[i]=='R')
{
num[3]++;
}
}
if(num[0]==m&&num[1]==m&&num[2]==m&&num[3]==m)//s已平衡
{
ans=0;
cout<<ans<<endl;
return 0;
}
for(int i=l;i<=r;i++)//[l,r]区间内各字符的个数
{
if(s[i]=='Q')
{
num[0]--;
}
else if(s[i]=='W')
{
num[1]--;
}
else if(s[i]=='E')
{
num[2]--;
}
else if(s[i]=='R')
{
num[3]--;
}
}
while(r<len&&l<len)//窗口未出界
{
int maxx=max(max(num[0],num[1]),max(num[2],num[3]));
int total=r-l+1;//可以更改的位置
total-=(maxx-num[0])+(maxx-num[1])+(maxx-num[2])+(maxx-num[3]);//填平操作
if(total>=0&&total%4==0)
{
if(s[l]=='Q')
{
num[0]++;
}
else if(s[l]=='W')
{
num[1]++;
}
else if(s[l]=='E')
{
num[2]++;
}
else if(s[l]=='R')
{
num[3]++;
}
ans=min(ans,r-l+1);
l++;//继续寻找更小区间
}
else//不符合条件 扩大区间
{
r++;
if(s[r]=='Q')
{
num[0]--;
}
else if(s[r]=='W')
{
num[1]--;
}
else if(s[r]=='E')
{
num[2]--;
}
else if(s[r]=='R')
{
num[3]--;
}
}
}
cout<<ans<<endl;
return 0;
}