各位相加(迭代/递归/数学)

88 阅读2分钟

首先该题如果用递归或者是迭代的方法来做很简单,我们下面主要想说的是该题隐藏的一个数学知识点——数根(题目所求即数根)

数根可以计算模运算的同余,对于非常大的数字的情况下可以节省很多时间。

数字根可作为一种检验计算正确性的方法。例如,两数字的和的数根等于两数字分别的数根的和。

另外,数根也可以用来判断数字的整除性,如果数根能被3或9整除,则原来的数也能被3或9整除

接下来讨论我们怎么求出树根。

我们把 1 到 30 的树根列出来。
原数: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
数根: 1 2 3 4 5 6 7 8 9  1  2  3  4  5  6  7  8  9  1  2  3  4  5  6  7  8  9  1  2  3 
可以发现数根 9 个为一组, 1 - 9 循环出现。我们需要做就是把原数映射到树根就可以,循环出现的话,想到的就是取余了。

结合上边的规律,对于给定的 n 有三种情况。

n 是 0 ,数根就是 0。

n 不是 9 的倍数,数根就是 n 对 9 取余,即 n mod 9。

n 是 9 的倍数,数根就是 9。

我们可以把两种情况统一起来,我们将给定的数字减 1,相当于原数整体向左偏移了 1,然后再将得到的数字对 9 取余,最后将得到的结果加 1 即可。

原数是 n,树根就可以表示成 (n-1) mod 9 + 1,可以结合下边的过程理解。

原数: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
偏移: 0 1 2 3 4 5 6 7 8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 
取余: 0 1 2 3 4 5 6 7 8  0  1  2  3  4  5  6  7  8  0  1  2  3  4  5  6  7  8  0  1  2  
数根: 1 2 3 4 5 6 7 8 9  1  2  3  4  5  6  7  8  9  1  2  3  4  5  6  7  8  9  1  2  3

class Solution {
public://这样也可
    int addDigits(int num) {
        if(!num)
        return 0;
        if(num%9==0)
        return 9;
        else
        return num%9;       

    }
};

下面也给出迭代和递归的写法

class Solution {
public://循环
    int addDigits(int num) {
        int sum=0,onum=num;
        while((num/10)!=0)
        {
            sum=0;
            onum=num;
            while(onum)
            {
                sum+=onum%10;
                onum/=10;
            }
            num=sum;
        }
        return num;
    }
};
class Solution {
public://递归
    int addDigits(int num) {  
        if(num<10)
        return num;
        else
        return addDigits(num%10+num/10);
    }
};