题目详情:
如果两个正整数组成它们的数字和相同则称它们互为友好数,给定正整数x,求比它大的最小的友好数。
例如x = 222, 输出231,因为2 + 2 + 2 = 6 = 2 + 3 + 1。
输入一个正整数x,由于输入数字较大,我们用字符串作为输入,字符串不包含首'0'。 (0 < x <= 10^1000),我们同样用字符串来表示输出。
--------------------------------------------------分割线-----------------------------------
1.我的做法是:
首先定义:(1)可加1位为本位数字小于9的数位;
(2)数字某位的剩余和为本位数后面的所有数位数字之和;
我的做法就是找到剩余和大于等于1的可加1数位,然后对该可加1位加1,然后将剩余和自减1,并将该位后面的数位通过减1后的剩余和够造成最小数。
对加1后面数位够造成最小数的方法很简单:
从最低位开始,如果剩余和大于等于9,此位为9,剩余和减9,否则此位为剩余和,前面其他位为0。
需要注意的是像990这样不存在剩余和大于等于1的可加1数位,需要在其最前面添加一位(即进位),值为1,然后剩余数位的构造同上面的方法。
2.代码如下:
此题hero的C++实现的函数名用了friend,但是friend在C++中是关键字,所以会出错,下面是C语言实现:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* friend (char* s){
int len=strlen(s);
char * res=(char*)malloc(sizeof(char)*(len+1));
int leftVal=s[len-1]-48;
//search the positon which can add 1
int i=len-2;
int index=len-1;
strcpy(res,s);
for(;i>=0;--i){
if(s[i]!='9'&&leftVal){
++res[i];
break;
}else
leftVal+=s[i]-48;
}
--leftVal;
if(i<0){
free(res);
res=(char*)malloc(sizeof(char)*(len+2));
res[len+1]='\0';
res[0]='1';
++res;
}
//make the min using leftVal
for(;index>i;--index){
if(leftVal>9){
res[index]=57;
leftVal-=9;
}else if(leftVal>0){
res[index]=leftVal+48;
leftVal=0;
}else if(leftVal==0){
res[index]=48;
}
}
if(i<0)--res;
return res;
}
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main(){
printf("%s\n",friend("290"));
printf("%s\n",friend("9"));
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
3.时间复杂度:O(length)