回文数(牛客练习赛71)题解

题目描述
Froggy 分别给出 10 个数码的出现次数,你需要找到一个由这些数码组成的最小的数,满足:
1. 这个数是回文的。
2. 不能有前导 0。

注:假设这个数字长度是 LL,那么这个数是回文的当且仅当对于任意的 i\in [1,L]i∈[1,L],第 ii 位的数码和第 L-i+1L−i+1 位的数码相同。
快来帮帮 Froggy 吧!
输入描述:
一行 10 个自然数,分别表示数码 0\sim 90∼9 的出现次数。
输出描述:
如果无解,只输出 “-1”。(不含引号)
否则,输出一个数表示最小的解。
示例1
输入
复制
0 2 4 2 0 2 0 0 0 0
输出
复制
1223553221
示例2
输入
复制
1 1 4 5 1 4 0 0 0 0
输出
复制
-1
示例3
输入
复制
4 0 2 3 0 0 0 2 0 0
输出
复制
20037373002
示例4
输入
复制
2 0 0 0 0 0 0 0 0 1
输出
复制
-1
说明
注意不能有前导 0。
示例5
输入
复制
1 0 0 0 0 0 0 0 0 0
输出
复制
0
备注:
保证输入的所有数都不超过 1010,且至少有一个数大于 00。

思路:这道题的思路其实就是把有前导零的情况和奇数的个数大于1情况排除,如果只有一个数(n==1)直接输出这个数,排除之前情况剩下的都是可以拼装回文数的,进行回文数的拼装,先写第一个和最后一个防止前导零的出现,之后对后面进行拼装就行了
AC代码:(记得多看一下注释)

#include <iostream>
#include <cstdio>
#include <cstring> 
#include <algorithm>
using namespace std; 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int a[10];
char b[1005];
int main(int argc, char** argv) {
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	int num=0,n=0;
	for(int i=0;i<10;i++){
		cin>>a[i];
		if(a[i]%2!=0){
			num++; //记录(0-9)有奇数的个数
		//	wo=i;
		} 
		n+=a[i];
	}
	//只有一个数
	 if(n == 1){
        for(int i = 0; i < 10; i++){
            if(a[i]){
                cout << i << endl;
                return 0;
            }
        }
    }
//	int flag=0,p=-1;
	if(num > 1 || n - a[0] <= 1 ){
	//个数为奇数的数大于一,有前导0的情况(a[0]的数量等于n-1)
        cout << "-1" << endl;
        return 0;
    }
	int k=1;
	if(a[0]%2!=0){
		b[n/2]='0';
	} 
	int n1=a[0]/2;
	//记录第一个和最后一个的值
	for(int i=1;i<10;i++){
		if(a[i]){
            if(a[i] == 1){
                continue;
            }
            b[0] = i + '0';//前半部分赋值
            b[n-1] = i + '0'; //后半部分赋值
            a[i] -= 2;
            break;
        }
	} 
	//记录(1到n-2)中间的值
	int temp=1;//记录需要填入目标数组位置变化
	for(int i=0;i<10;i++){
		 if(a[i]){
            if(a[i]%2!=0){//把奇数的数字放在中间
                b[n/2] = '0' + i;
            }
            int j;
            for(j = 0; j < a[i] / 2; j++){
                b[temp+j] = i + '0';//前半部分赋值
                b[n-temp-j-1] = i + '0'; //后半部分赋值
            }
            temp += j;//向后移动a[i]-1个位置
        }
	}
	for(int i=0;i<n;i++){
		cout<<b[i];
	}
	//cout<<endl;
	return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值