题目描述:
链接:https://ac.nowcoder.com/acm/contest/3402/D
来源:牛客网
米多立亚少年此时正在学习one for all全覆盖5%,但是他不想努力了,于是哆啦A梦拿出神奇道具帮助米多立亚少年,让他可以1分钟学会全覆盖。当米多立亚少年使用这个道具的时候,道具的屏幕上会出现一个字符串(只由’0’ , ‘1’ , ‘2’ 三种字符构成) 。
这些字符串有如下的交换规则:对于相邻的两个字符,‘01’可以变成’10’ , ‘10’可以变成’01’ , ‘12’可以变成’21’ , ‘21’可以变成’12’,可以交换无数次。
米多立亚少年需要尽快反馈给道具一个最小字典序的字符串,你可以帮助他吗?
输入描述:
多组测试用例,保证 ∑|s|≤ 5*107;
每组测试用例一行,表示道具屏幕上出现的只包含‘0’,‘1’,‘2’的字符串s,(0<|s| ≤ 106,|s|为字符串s的长度)
输出描述:
输出交换后的最小字典序的字符串
输入样例:
101022
01010120
0121021
输出样例:
001122
00011120
0111202
核心思想:
0和2的相对位置固定,1位置随便摆放。要使字典序最小,将全部的1挪到第一个2之前即可。
代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e6+20;
char s[N];
int main()
{
while(~scanf("%s",s))
{
int len=strlen(s),cnt=0,p=len;//cnt记录1的个数,p为第一个2的位置
//得到cnt和p
for(int i=len-1;i>=0;i--)
if(s[i]=='1')
cnt++;
else if(s[i]=='2')
p=i;
//输出p之前的0
for(int i=0;i<p;i++)
if(s[i]=='0')
printf("0");
//在第一个2之前输出全部的1
for(int i=0;i<cnt;i++)
printf("1");
//输出后续非1字符
for(int i=p;i<len;i++)
if(s[i]!='1')
printf("%c",s[i]);
printf("\n");
}
return 0;
}