题目说明
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数
- 输入:38
- 输出:2
- 解释:各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。
题目解答
首先用常规的思路想,肯定是要用到循环的,首先计算出给定数字的各位之和,然后再看得到的结果,如果该结果不为一位数,则继续之前的步骤进行计算,否则退出循环,输出结果。问题的解答步骤可以描述如下:
- 计算完数值 num 的各位之和,并存到一个临时变量 temp 中;
- 若 temp < 10,则重复第1步;否则退出循环。
int addDigits(int num) {
int temp=0;
while (num) {
temp += (num%10);
num /= 10; // n等于0意味着一轮算完了
if (num == 0) {
if (temp < 10) {
break;
} else {
num = temp;
temp = 0; // 一定要记得将temp归零
}
}
}
return temp;
}
上面代码中有一个 num%10
,以前给你们说过,“ % ”是 取余运算 ,那这句话有什么用呢?
我们看这个:11%10=1; 22%10=2
对,没错:%运算在数值运算中常常被用来取一个数的个位(最低位)(你们可以写一个循环,从最右边开始,一个一个取,就变成了了取每一位) (这句话记下来!有用!!!)
上面加粗的话中说:用一个循环,一个一个取,但是这个没有赋值语句,每一次取的不都是一样的吗?(自己试一下,敲一下!)
所以上面代码中还有一句:num/10
,而且注意到没有,这句代码被放在了上面取余代码的紧贴着下一行。
再来看这个:11/10=1;22/10=2;32/10=3
对了,整数运算取整数部分这已经是个常识了。
所以,先取余再整除,下一次取余时就是(原数据的)上一位了。
妙啊!
上述代码有一个地方需要注意,第13行,一开始我没有加上第13行,这意味着temp每次计算完一轮之后都没有归零,一直在累加上次循环完后的结果,导致程序陷入死循环中。
看到这里,这一题你们就已经掌握了。但是,正所谓“富贵险中求”,不对,是“不满足才有更好的”。(其实都差不多)…
想接触算法的可以继续往下看
现在来尝试不用循环解决问题。
我们来分析一下这种变换之后的数字的规律,设 num=abc num = abcnum=abc,即 s1=100a+10b+c s1 = 100a+10b+cs1=100a+10b+c,则变换之后,s2=a+b+c s2 = a+b+cs2=a+b+c,有s1−s2=99a+9b=9(11a+b) s1-s2=99a+9b=9(11a+b)s1−s2=99a+9b=9(11a+b),差值是9的倍数,s2 s2s2是s1 s1s1去除部分9的倍数之后的结果。若s2 s2s2不为一位数,假设s2=10x+y s2=10x+ys2=10x+y,则s3=x+y s3=x+ys3=x+y,有s2−s3=9x s2-s3=9xs2−s3=9x,差值也为9的倍数,s3 s3s3是s2 s2s2去除部分9的倍数之后的结果。即,每次变换前后的差值都为9的倍数,故最后的结果总为num%9 num%9num%9。
但是,结果为num num%9num的话,结果明显是小于9的。当num为9的时候,结果明显为9,但是依据我们前面的分析得出来是0。故可以在计算的时候进行判断,如果num%9=0 num%9=0 num%9=0,则输出9 99:
int addDigits(int num) {
int temp=0;
if (num>0) {
temp = num%9;
if (temp == 0) {
temp = 9;
}
}
return temp;
}
更有甚者,我们可以用三目表达式,一行代码解决问题:
int addDigits(int num) {
return num==0?0:(num%9==0?9:num%9);
}
完。
好好体会,多敲代码!(别光看)
我是云风清,来CSDN,一起探索编程的奥妙!