【思维题】CodeForce 1009B Minimum Ternary String

版权声明:Johnson https://blog.csdn.net/m0_38055352/article/details/91294676

这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!

一、题目大意

题目的意思就是给一个只包含’0’,‘1’,‘2’的字符串,你可以将其中相邻的’0’和’1’进行交换,也可以将其中相邻的’1’和’2’进行交换,但是不能交换相邻的’0’和’2’,求给定字符串之后可以换出的最小字典序的字符串。

二、题目思路以及AC代码

首先这道题不考虑时间的话是可以暴力求解的,你只需要定义正确交换的规则,按模拟题的思路去做,就可以得到正确的答案,但需要注意的是给定的字串长度是1e5,暴力的话需要遍历很多遍字串,如果数据不是很水的话,是很难通过的。

那么我们就要开始找交换结果的规律了,我们通过分析,可以发现交换后的字串一定是以下形式的:00…0111…11200…0200…0200.0200.00,这是什么意思呢?就是一开始给定字串之后,前面的0肯定是不用被交换的,然后因为1可以和所有的字串进行交换,那么紧接着肯定是所有的1(有人可能会奇怪为什么后面的0不放在这,这是因为0和2不能交换,所以其只能被阻隔在后面),然后就是2了,由于0不能和2交换,所以两个2之间的0还是得在两个2之间,后面就都是这样了,找到这样的规律之后,我们只需要一开始扫描一遍,把我们需要的数据储存起来,然后再寻找答案的时候就会快很多啦!大致就是O(n)的复杂度。

下面给出AC代码:

#include <iostream>
#include <string>
#include <cstring>
#define MAX 100010
using namespace std;

string str;
int fTwo[MAX];
int nZero[MAX];
int nOne;

int main()
{
	cin >> str;
	int len = str.length();

	int size = 0;
	for (int i = 0; i < len; i++) {
		if (str[i] == '0') {
			nZero[size]++;
		}
		else if (str[i] == '1') {
			nOne++;
		}
		else {
			fTwo[size++] = i;
		}
	}

	string ans = "";
	ans += string(nZero[0], '0');
	ans += string(nOne, '1');
	if (size) {
		ans += '2';
		for (int i = 1; i < size; i++) {
			if (nZero[i]) {
				ans += string(nZero[i], '0');
			}
			ans += '2';
		}
		if (nZero[size]) ans += string(nZero[size], '0');
	}

	cout << ans << endl;

    return 0;
}

如果有问题,欢迎大家指正!!!

猜你喜欢

转载自blog.csdn.net/m0_38055352/article/details/91294676