程序设计思维 C - 平衡字符串(尺取法)

题目

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

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

Output
一个整数表示答案

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’.

思路

这题需要用到尺取法(双指针法)。
尺取法的使用条件为:
① 遍历一个连续的区间。
② 两个指针移动的方向一致。
将输入的字符串存在字符串s中,设字符串s的长度为len。统计字符串s中‘Q’、‘W’、‘E’、‘R’的个数,设个数分别为qNum、wNum、eNum、rNum。
对于给定的一段区间[L, R],设区间的长度为total。统计这个区间中‘Q’、‘W’、‘E’、‘R’的个数,设个数分别为qInSub、wInSub、eInSub、rInSub。设
qNotInSub = qNum - qInSub;
wNotInSub = wNum - wInSub;
eNotInSub = eNum - eInSub;
rNotInSub = rNum - rInSub;
maxNotInSub = MAX(qNotInSub, wNotInSub, eNotInSub, rNotInSub);
free = total - (maxNotInSub - qNotInSub) - (maxNotInSub - wNotInSub) - (maxNotInSub - eNotInSub) - (maxNotInSub - rNotInSub)。
若 free ≥0 且为 4 的倍数,则L++、minLen = MIN(minLen, total);否则R++。
循环上述过程直到遍历完整个字符串。
输出minLen。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

string s;
int qNum, wNum, eNum, rNum; // 记录4个字母在初始输入的字符串中的个数
int minLen;


int main()
{
	while (cin >> s) {
		int len = s.length();
		qNum = 0, wNum = 0, eNum = 0, rNum = 0;
		for (int i = 0; i < len; i++) { //统计4个字母在输入的字符串中的个数
			switch (s[i])
			{
			case 'Q':
				qNum++;
				continue;
			case 'W':
				wNum++;
				continue;
			case 'E':
				eNum++;
				continue;
			case 'R':
				rNum++;
				continue;
			default:
				continue;
			}
		}

		if (qNum == len / 4 && wNum == len / 4 && eNum == len / 4 && rNum == len / 4) {
			cout << 0 << endl;
			continue;
		}

		int left = 0, right = 0, minLen = len + 1;

		while (right < len && minLen>1) {
			int qInSub = 0, wInSub = 0, eInSub = 0, rInSub = 0;
			for (int i = left; i <= right; i++) {
				switch (s[i])
				{
				case 'Q':
					qInSub++;
					continue;
				case 'W':
					wInSub++;
					continue;
				case 'E':
					eInSub++;
					continue;
				case 'R':
					rInSub++;
					continue;
				default:
					continue;
				}
			}
			int qNotInSub = qNum - qInSub;
			int wNotInSub = wNum - wInSub;
			int eNotInSub = eNum - eInSub;
			int rNotInSub = rNum - rInSub;

			int maxNotInSub = max(max(qNotInSub, wNotInSub), max(eNotInSub, rNotInSub));
			int total = right - left + 1;
			int free = total - (maxNotInSub - qNotInSub) - (maxNotInSub - wNotInSub) - (maxNotInSub - eNotInSub) - (maxNotInSub - rNotInSub);

			if (free >= 0 && free % 4 == 0) {
				if (minLen > total) minLen = total;
				left++;
			}
			else {
				right++;
			}
		}

		cout << minLen << endl;
	}

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值