「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。
题目
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。
示例 1:
输入: num = 38
输出: 2
解释: 各位相加的过程为:
38 --> 3 + 8 --> 11
11 --> 1 + 1 --> 2
由于 2 是一位数,所以返回 2。
示例 2:
输入: num = 0
输出: 0
提示:
0 <= num <= 2^31 - 1
进阶: 你可以不使用循环或者递归,在 O(1) 时间复杂度内解决这个问题吗?
思考
这是一道有意思的题目,难度简单。
首先我们先理解题意。题目是说将非负整数 num 的各个位上的数字相加,直到结果为一位数。那么,我们首先可以想到的是使用递归,每次取出各个位上的数字。如何取出各个位上的数字呢?我们可以将数字 num 对10求余,余数就是个位上的数字。接着,将数字右移一位,再继续对10求余。这样递归下去,直至和为一位数为止。
还有一种很巧妙的解法:数字根。我们可以列出数字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
可以发现数根是 1 ~ 9 循环出现。那么,我们需要把原数映射到数根,这可以通过取余运算符 % 去实现。
解答
方法一:递归
var addDigits = function(num) {
if (num < 10) {
return num
}
let res = 0
while (num != 0) {
res += num % 10
num = parseInt(num / 10)
}
return addDigits(res)
}
// 执行用时:72 ms, 在所有 JavaScript 提交中击败了95.80%的用户
// 内存消耗:43.2 MB, 在所有 JavaScript 提交中击败了5.13%的用户
方法二:数字根
var addDigits = function(num) {
return (num - 1) % 9 + 1
}
// 执行用时:60 ms, 在所有 JavaScript 提交中击败了99.84%的用户
// 内存消耗:41.8 MB, 在所有 JavaScript 提交中击败了5.45%的用户
复杂度分析
- 时间复杂度:O(1)
- 空间复杂度:O(1)