回文字(牛客竞赛题解)

题目描述

Froggy 分别给出 10 个数码的出现次数,你需要找到一个由这些数码组成的最小的数,满足:

1. 这个数是回文的。

2. 不能有前导 0。

注:假设这个数字长度是 L,那么这个数是回文的当且仅当对于任意的 i∈[1,L],第 i 位的数码和第 L−i+1位的数码相同。

快来帮帮 Froggy 吧!

输入描述:

一行 10 个自然数,分别表示数码 0∼9 的出现次数。

输出描述:

如果无解,只输出 “-1”。(不含引号)

否则,输出一个数表示最小的解。

备注:

保证输入的所有数都不超过 10,且至少有一个数大于 0。

思路简述:

1.输入次数是按照从0到9的顺序输入的,这样输入也使得我们在最后找最小数字的时候,如果第一位是0字符,可以直接将第一位字符和1字符交换,这样得到的就是最小的数字

2.同时我们得考虑输入每个字符的次数是否是偶数,如果是偶数,当然可以构成回文数字,但如果有奇数,得分情况,如果只有一个奇数,那么只要将这个字符放在中间即可,但如果是两个奇数次数的字符,那么就不能构成回文字符。所以下面的mid就是起这样的一个功能

3.对于可以成对出现的字符,我们只要将一个存储在ans之中即可。这样会使得我们在最后输出回文字符的时候只要将ans逆置即可、

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	int times = 0;
	string mid, ans;
	for (int i = 0; i < 10; i++)
	{
		cin >> times;//输入该字码出现的次数
		//先判断这个次数是不是偶数
		if (times & 1)//二级制按位且。如果是奇数,就运行下面的语句
			mid += ('0' + i);//这里表示在字符串末尾+上一个字符,这些字符就表示次数是奇数的字码
		for (int j = 0; j < times / 2; j++)//表示循环的是次数的一半
			ans += ('0' + i);//表示的是每一个字码的次数的偶数次的一半
		//这里的mid是保存的字码是否是奇数,ans表示的是偶数次/2,也就是说ans中出现了一个字符,就表示这个字符的实际次数是2次
	}
	if (mid.size() > 1)//size获取的是字符串mid的长度
		puts("-1");//表示的是奇数的字符超过了1个,就不能成立,是因为如果是一个字符多出来,我们可以将这个字符放在中间,构成回文字符,如果不止一个,就不能放在中间构成回文字符
	else//表示是0或者1的情况
	{
		int k = 0;
		while (k < ans.size() && ans[k] == '0')
			k++;
		if (k == ans.size() && k != 0)//这里得考虑完全,如果出现了0字符,但是只是出现了0字符,就得考虑首字母是否是0的情况
			puts("-1");
		else
		{
			swap(ans[k], ans[0]);//将第一个不为0的字码和0交换
			cout << ans << mid;//这里的ans只是一半的数据,而且要的是最小的数,按照上面的得到ans和mid的方法,我们得到的就是升序的字符串,所以上面只需要将第一个0字符换为非1字符即可
			reverse(ans.begin(), ans.end());//将ans字符串首位倒置,得到的是回文字符串
			cout << ans<<endl;
		}
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值