开启掘金成长之旅!这是我参与「掘金日新计划 · 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)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
这道题目我的思路很简单,当数字大于10时,我们每次取模10后得到的数字相加,然后除以10。如此循环往复直到数字小于10。
结果是可以的,顺利通过了测试。
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
不是一次通过的,刚开始当内层循环结束时,result没有加上最终的num。后来通过调试代码,发现了这个问题,加了一行代码就解决了。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
似乎,但凡是「将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的倍数的一系列考量。
作者:掘金酱
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。