LeetCode探索(31):258-各位相加

140 阅读2分钟

「这是我参与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)

参考