英雄会(csdn 高校俱乐部)题解之友好数(1)

题目详情:

如果两个正整数组成它们的数字和相同则称它们互为友好数,给定正整数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)

 

你可能感兴趣的:(题解,英雄会,pongo,CSDN英雄会,友好数1)