LeetCode 258. 各位相加

56 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情

LeetCode 258. 各位相加

一、题目描述:

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。

示例 1:

输入: num = 38

输出: 2

解释: 各位相加的过程为:

38 --> 3 + 8 --> 11

11 --> 1 + 1 --> 2

由于 2 是一位数,所以返回 2。

示例 1:

输入: num = 0

输出: 0

提示:

0 <= num <= 2^31 - 1

进阶:你可以不使用循环或者递归,在 O(1) 时间复杂度内解决这个问题吗?

来源:力扣(LeetCode)

链接:leetcode.cn/problems/ad…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    这道题目我的思路很简单,当数字大于10时,我们每次取模10后得到的数字相加,然后除以10。如此循环往复直到数字小于10。

    结果是可以的,顺利通过了测试。

  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    不是一次通过的,刚开始当内层循环结束时,result没有加上最终的num。后来通过调试代码,发现了这个问题,加了一行代码就解决了。

  3. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

    似乎,但凡是「将X进制各个位置上的数加起来」的操作,都会和 mod (X - 1) 搭上边。

    如果是二进制,类似的问题就是,将一个数字num的二进制的每一位都加起来,然后反复执行,直到得到0或1为止。

    结论就是,如果 num 是 0 那么结果就是 0, 否则结果就是 1 (因为任何数都是1的倍数), 也和题解结论一致。

    func addDigits(num int) int {
        return (num-1)%9 + 1
    }
    

三、AC 代码:

func addDigits(num int) int {
    result := 10
    for result >= 10{
        result = 0 
        for num >= 10 {
            result += num % 10
            num /= 10
        }
        result += num
        fmt.Println(num,result)
        num = result
    }
​
    return result
}

执行结果:通过

执行用时:4 ms, 在所有 Go 提交中击败了40.44%的用户

内存消耗:2 MB, 在所有 Go 提交中击败了61.75%的用户

通过测试用例:1101 / 1101

四、总结:

说一下(num-1)%9+1的意义。

基数是10的数字根是0到9的整数,但是一个数如果直接%9,范围是 0到8,和数字根的定义不符。

什么样的数字他的数字根应该是9呢?就是num本身是9的倍数。num%9对于本身是9的倍数一律返回0,不是我们希望看到的结果。

注意是取模公式。 根据取模公式有(num-1)%9=(num%9-1%9)%9=(num%9-1)%9。 num%9-1的范围是 -1到7,取模语言中 (-1到7)%9的范围变成了0-8,对应到每个num上,其-1再%9后的运算结果比直接%9少了1,所以为了使数字根答案不变,我们直接加回1即可。 0也是9的倍数,但是他的数字根是0,这番操作后是9,所以需要额外操作。

总而言之,这个做法的主要意义是绕开了对num是不是9的倍数的一系列考量。

作者:掘金酱

链接:juejin.cn/post/706970…

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。