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之外的字符匹配完毕之后,剩余的字符

扫描二维码关注公众号,回复: 10399753 查看本文章
		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;

}


发布了29 篇原创文章 · 获赞 14 · 访问量 1250

猜你喜欢

转载自blog.csdn.net/weixin_44552961/article/details/105233811