Week5--作业 -- C -- 平衡字符串[差分数组]

题目描述

一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。
如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?
如果 s 已经平衡则输出0。

输入

一行字符表示给定的字符串s

输出

一个整数表示答案

样例输入

QWER

样例输出

0

思路

综述

这道题主要考察了一个新的方法:尺取法
即:维护双指针,遍历数组的过程中,用两个指针向相同方向进行扫描

使用条件:

1)所求解答案为一个连续的区间
2)区间左右端点移动有明确方向

对于本题:

满足以上两个条件可以用尺取法
1)是一个连续区间
2)所求皆的左右端点有明确方向
当前[L,R]满足要求L++
当前[L,R]不满足要求R++

给定一个[L,R]判断是否满足条件

Step1:用四个字符记录不在区间里的’Q’、‘W’、‘E’、'R’个数
Step2:先使得区间外的四个字符数量一致,然后判断剩余的是否是4的倍数
具体做法:四个字符的个数分别和最多字符个数的差值设为b
区间[L,R]中字符个数减去b即为剩余字符个数,判断这个数是否是4的倍数

过程
Step1:初始化

先判断该字符串是否符合题意

			for (int i = 0; i < s.size(); i++) {
				if (s[i] == 'Q')sum1++;
				else if (s[i] == 'W')sum2++;
				else if (s[i] == 'E')sum3++;
				else if (s[i] == 'R')sum4++;
			}
			if (sum1 == sum2 && sum2 == sum3 && sum3 == sum4) {
				cout << "0" << endl;
				return 0;
			}
Step2:操作A数组 => 操作B数组

计算FREE:也就是将LR之外的字符匹配完毕之后,剩余的字符

		int MAX;
		MAX = sum1;
		if (sum2 > MAX)MAX = sum2;
		if (sum3 > MAX)MAX = sum3;
		if (sum4 > MAX)MAX = sum4;
		int FREE;
		int tot;
		tot = r - l + 1;
		FREE = tot - (MAX - sum1) - (MAX - sum2) - (MAX - sum3) - (MAX - sum4);

Step3:判断LR区间是否符合题意
		if (FREE == 0 && FREE % 4 == 0) {
			flag = true;
		}
		else {
			flag = false;
		}
Step4:移动

如果符合题意则L++
反之R++

		if (flag) {

			if (r - l + 1 < ans)ans = r - l + 1;

			if (s[l] == 'Q')sum1++;
			else if (s[l] == 'W')sum2++;
			else if (s[l] == 'E')sum3++;
			else if (s[l] == 'R')sum4++;
			l++;
		}
		else {
			r++;
			if (s[r] == 'Q')sum1--;
			else if (s[r] == 'W')sum2--;
			else if (s[r] == 'E')sum3--;
			else if (s[r] == 'R')sum4--;
			
		}

总结

连等的情况
如下所示,如果出现连等的情况,计算规则:
从左到右计算,第一对的bool值也就是0或者1再和后面的进行==计算
在这里插入图片描述在这里插入图片描述

代码

#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
int main() {
	string s;
	int l, r;
	cin >> s;
	int tot;
	l = 0;
	r = 0;
	int sum1, sum2, sum3, sum4;//Q W E R
	sum1 = sum2 = sum3 = sum4 = 0;
	int ans = 10000000;

	sum1 = sum2 = sum3 = sum4 = 0;
	while (l <= r && r < s.size()) {
		
		
		//初始化
		if (l == 0 && r == 0) {
			for (int i = 0; i < s.size(); i++) {
				if (s[i] == 'Q')sum1++;
				else if (s[i] == 'W')sum2++;
				else if (s[i] == 'E')sum3++;
				else if (s[i] == 'R')sum4++;
			}
			if (sum1 == sum2 && sum2 == sum3 && sum3 == sum4) {
				cout << "0" << endl;
				return 0;
			}
			if (s[0] == 'Q')sum1--;
			else if (s[0] == 'W')sum2--;
			else if (s[0] == 'E')sum3--;
			else if (s[0] == 'R')sum4--;
		}

		int MAX;
		MAX = sum1;
		if (sum2 > MAX)MAX = sum2;
		if (sum3 > MAX)MAX = sum3;
		if (sum4 > MAX)MAX = sum4;
		int FREE;
		int tot;
		tot = r - l + 1;
		//计算剩余字符数目
		FREE = tot - (MAX - sum1) - (MAX - sum2) - (MAX - sum3) - (MAX - sum4);
		bool flag;
		if (FREE == 0 && FREE % 4 == 0) {
			flag = true;
		}
		else {
			flag = false;
		}
		//移动
		if (flag) {
			if (r - l + 1 < ans)ans = r - l + 1;
			if (s[l] == 'Q')sum1++;
			else if (s[l] == 'W')sum2++;
			else if (s[l] == 'E')sum3++;
			else if (s[l] == 'R')sum4++;
			l++;
		}
		else {
			r++;
			if (s[r] == 'Q')sum1--;
			else if (s[r] == 'W')sum2--;
			else if (s[r] == 'E')sum3--;
			else if (s[r] == 'R')sum4--;
			
		}
	}
	cout << ans << endl;

}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值