LeetCode:Add Digits

https://leetcode.com/problems/add-digits/

Given a non-negative integer num, repeatedly add all its digits until the result has only one digit.

For example:

Given num = 38, the process is like: 3 + 8 = 111 + 1 = 2. Since 2 has only one digit, return it.

Follow up:
Could you do it without any loop/recursion in O(1) runtime?


My Solution:

1.      最笨的办法是两次循环。里层循环执行将num的各个位相加,外层循环判断结果是否为个位数,是否还需继续执行各位相加。

int addDigits(int num) {
    while(num > 9) {
        int sum = 0;
        while(num > 0) {
            sum += num % 10;
            num /= 10;
        }
        num = sum;
    }
    return num;
}

2.      考虑到输入参数int num,其表示成正整数最多10位,各位相加的和最大的数是1,999,999,999,相加之和sum1不超过82。而使得sum1的两位相加之和sum2最大的sum1取值为79,对应的sum216。令sum2的各位之和为sum3,。若sum2为两位数,则最大值是16,sum31+6=7;若sum21位数,则最大值是9sum3=sum2=9。综上,给定32位正整数num,最多执行3次各位相加的操作即可得到最终结果。即num=>sum1=>sum2=>sum3。其中,num最多为10位,sum12位,sum22位,sum3一定为1位。故不循环,硬编码相加。

int addDigits(int num) {
    // 第一次
    int sum = num / 1000000000
            + (num / 100000000) % 10
            + (num / 10000000) % 10
            + (num / 1000000) % 10
            + (num / 100000) % 10
            + (num / 10000) % 10
            + (num / 1000) % 10
            + (num / 100) % 10
            + (num / 10) % 10
            + num % 10;
    num = sum / 10 + sum % 10;// 第二次
    num = num / 10 + num % 10;// 第三次
    return num;
}

效率有提高,厚着脸皮不知道能不能算是O(1)。有很多无用计算是确实的。

3.      用数学方法计算代数解(恕我愚笨没有找到)。

4.      Hint:找规律,发现当num从1开始递增时,结果为1-9不断循环。故规律为ret = (num-1) % 9 + 1;或 ret = num - (num - 1) / 9 * 9;

int addDigits(int num) {
    return (num - 1) % 9 + 1;
}
正是我想要的结果。可这是看了三个Hint之后才想出来的。。
结论:可能是考研过了太久了,当初做无穷级数求和的题目就是先写出几项看看规律。现在连最基础的找规律都没试一试。以后谨记。

PS:找到规律后视图用数学进行证明,发现自己大致可以理解,就是当num自增1时,num的各位之和也自增1,或减去9k再自增1。而且,某个数减去9k之后,若其大于9,则在继续计算各位之和时,这个9k可以被抵消掉。但严谨的数学证明还是不会做。


请教ALF后得证:

证明:对任意n大于10,n与n的各位之和模九同余。(ai * 10^n = ai * (1 + 10^n - 1) = ai + ai * 999...999<i个9> = ai <mode 9>),不断地将结果的各位相加,最终得到一位数k。当k为1-8时,k和n模九同余,故k=n%9。当n%9为0时,k=9。


早知如此本科不如学数学!!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值