csdn英雄会(pongo)题解之回文数--源代码、测试用例、运行结果

#include <stdio.h>
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
class Test {
public:
	static void getMaxHw(int sum,int len,std::string&str){
		//求各位数字之和为sum,长度为len的最小回文,保存在str
		//sum>=2
		int times=len/2;
		for(int i=0;i<times;++i){
			int sum2=sum/2;
			int val=sum2>=9?9:sum2;
			int valC=48+val;//将数字val转换为相应的字符
			str[i]=valC;
			str[len-1-i]=valC;
			sum-=val;
			sum-=val;
		}
		if(len%2)
			str[times]=48+sum;
	}
	static void getMinHw(int sum,int len,std::string&str){
		//求各位数字之和为sum,长度为len的最小回文,保存在str
		//sum>=2
		int times=len/2;
		int val=1;
		int val2=2;//2*val
		for(int i=0;i<times;++i){
			int sub=sum-val2-(len-2*(i+1))*9;
			if(sub>0){//如果剩余数字全为9,仍不能凑够sum	
				val+=sub/2+sub%2;
				val2=val+val;//
			}
			int valC=48+val;
			str[i]=valC;
			str[len-1-i]=valC;
			sum-=val2;
			val=0;
			val2=0;
		}
		if(len%2)
			str[times]=48+sum;
	}
	static void getMinHw0(int sum,int len,std::string&str){
		//求各位数字之和为sum,长度为len的最小回文,首位从0开始枚举,保存在str
		int times=len/2;
		for(int i=0;i<times;++i){
			int val=0;
			int val2=0;//2*val
			int sub=sum-val2-(len-2*(i+1))*9;
			if(sub>0){			
				val+=sub/2+sub%2;
				val2=val+val;//
			}
			int valC=48+val;
			str[i]=valC;
			str[len-1-i]=valC;
			sum-=val2;

		}
		if(len%2)
			str[times]=48+sum;
	}
	static void getNear(int sum,std::string&str1,std::string&str2){
		//各位数字之和sum>=2,字符串长度len>=2
		//str2为和str1各位数字之和相同,且大于str1的最小回文
		int len=str1.size();
		int times=len/2;
		int index=-1;
		bool hasFind=false;
		int str2Btstr1=0;
		int reserve=0;
		int i=0;
		for(i=0;i<times;++i){
			int val=str1[i]-48;
			int val2=val+val;//2*val
			int sub=sum-val2;
			if(sub<0){			
				val+=sub/2+sub%2;
				val2=val+val;
				if(-1==index){
					index=i-1;
					reserve=sum;
					break;
				}
			}else if((sub-=(len-2*(i+1))*9)>0){
				
				hasFind=true;
				val+=sub/2+sub%2;
				val2=val+val;
			}
			int valC=48+val;
			str2[i]=valC;
			str2[len-1-i]=valC;
			if(valC>str1[len-1-i])
				str2Btstr1=1;
			else if(valC<str1[len-1-i])
				str2Btstr1=-1;
			else {
				//不影响大小性
			}
			sum-=val2;
		}
		if(i==times&&len%2){//i==times很有必要
			int tmp=sum+48;
			if(tmp<str1[times]){
				if(-1==index){
					index=times-1;
					reserve=sum;
				}			
			}else if(tmp>str1[times]){
				hasFind=true;
			}
			str2[times]=tmp;	
		}
		if(hasFind)
			return;

		if(-1!=index){
			while(reserve<2||str2[index]=='9'){//找到可加1的位置
				//当内部之和大于2,且本位数字不为9时才能加1
				reserve+=2*(str2[index]-48);
				--index;
			}
			++str2[index];
			++str2[len-1-index];
			reserve-=2;
			int tmpLen=len-index*2-2;
			std::string subStr(tmpLen,'0');
			getMinHw0(reserve, tmpLen,subStr);
			int j=0;
			for(int i=index+1;i<=len-1-index-1;++i){
				str2[i]=subStr[j];
				++j;
			}
		}else{		
			if(1==str2Btstr1)
				return;	
			else{			
				index=times-1;
				reserve=0;
				if(len%2){
					reserve+=str2[times]-48;
				}
				while(reserve<2||str2[index]=='9'){
					reserve+=2*(str2[index]-48);
					--index;
				}
				++str2[index];
				++str2[len-1-index];
				reserve-=2;
				int tmpLen=len-index*2-2;
				std::string subStr(tmpLen,'0');
				getMinHw0(reserve, tmpLen,subStr);
				int j=0;
				for(int i=index+1;i<=len-1-index-1;++i){
					str2[i]=subStr[j];
					++j;
				}
			}
		}
	}
    static string palindrom (string   a){
		int len=a.length();
		int sum=0;	
		for(int i=0;i<a.length();++i)
			sum+=a[i]-48;
		if(1>=sum)return "Impossible";
		if(1==len)//一位数
			if(sum%2){
				std::string str(3,'0');
				getMinHw(sum,3,str);	
				return str;
			}else{
				std::string str(2,'0');
				getMinHw(sum,2,str);
				return str;
			}	

		//sum>=2,位数>=2
		if(sum%2){//和为奇数,那么所求的回文位数也得是奇数
			if(0==len%2){//字符串位数为偶数,那么位数为字符串位数+1,各位数字之和为sum的最小回文即为所求
				std::string str(len+1,'0');
				getMinHw(sum,len+1,str);
				return str;
			}else{//字符串位数为奇数
				std::string strMax(len,'0');
				getMaxHw(sum,len,strMax);
				if(strMax.compare(a)>0){
					std::string str(a);
					getNear(sum,a,str);
					return str;
				}else{
					//和为奇数,且和字符串位数、各位数字之和相同的最大回文数小于等于字符串
					//那么位数为字符串位数+2(确保位数是奇数),各位数字之和为sum的最小回文即为所求
					std::string strMin(len+2,'0');
					getMinHw(sum,len+2,strMin);
					return strMin;
				}
			}
		}else{//和为偶数
				std::string strMax(len,'0');
				getMaxHw(sum,len,strMax);
				if(strMax.compare(a)>0){
					std::string str(a);
					getNear(sum,a,str);
					return str;
				}else{
					//和为偶数,且和字符串位数、各位数字之和相同的最大回文数小于等于字符串
					//那么位数为字符串位数+1,各位数字之和为sum的最小回文即为所求
					std::string strMin(len+1,'0');
					getMinHw(sum,len+1,strMin);
					return strMin;
				}
		}
    }
};
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main(){   
	clock_t t1=clock();
	std::cout<<"测试用例"<<std::endl;
	cout<<Test::palindrom("1234123")<<endl;
	cout<<Test::palindrom("1324321")<<endl;
	cout<<Test::palindrom("1234444")<<endl;
	cout<<Test::palindrom("399212")<<endl;
	cout<<Test::palindrom("22222")<<endl;
	cout<<Test::palindrom("2213")<<endl;
	cout<<Test::palindrom("1014")<<endl;
	cout<<Test::palindrom("2231")<<endl;
	cout<<Test::palindrom("11111111")<<endl;
	cout<<Test::palindrom("111111118")<<endl;
	cout<<Test::palindrom("111111139")<<endl;
	cout<<Test::palindrom("121")<<endl;
	cout<<Test::palindrom("9999")<<endl;
	cout<<Test::palindrom("9989")<<endl;
	cout<<Test::palindrom("9919")<<endl;
	cout<<Test::palindrom("9199")<<endl;
	cout<<Test::palindrom("10001")<<endl;
	cout<<Test::palindrom("8989")<<endl;
	cout<<Test::palindrom("12341234")<<endl;
	cout<<Test::palindrom("37532")<<endl;
	clock_t t2=clock();
	std::cout<<(t2-t1)/double(CLOCKS_PER_SEC)<<std::endl;
} 
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
运行结果:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值