Easy
题目描述
给定一个非负整数 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) 时间复杂度内解决这个问题吗?
提示:
- 上述过程的朴素实现是显而易见的。你能想出其他方法吗?
- 所有可能的结果是什么?
- 它们是周期性出现还是随机出现?
- 你可能会发现数字根的维基百科文章很有用。
解题思路
这道题有两种经典解法:模拟法和数学公式法。
解法一:模拟法 直接按照题意模拟整个过程。当数字大于等于10时,不断计算各位数字之和,直到结果为个位数。这种方法时间复杂度为O(log n),因为每次操作都会显著减少数字的位数。
解法二:数学公式法(推荐) 这道题实际上是求数字根(Digital Root)。通过数学分析可以发现规律:
- 如果 num = 0,结果为 0
- 如果 num 能被 9 整除且 num ≠ 0,结果为 9
- 否则结果为 num % 9
这个规律可以用一个简洁的公式表示:1 + (num - 1) % 9(当num > 0时)。
原理解释:任何正整数的数字根等于该数对9的余数,特殊情况是当余数为0时结果为9。这是因为一个数减去其各位数字之和必能被9整除(同余定理)。
数学公式法的时间复杂度为O(1),空间复杂度为O(1),是最优解法。
代码实现
class Solution {
public:
int addDigits(int num) {
if (num == 0) return 0;
return 1 + (num - 1) % 9;
}
};
class Solution:
def addDigits(self, num: int) -> int:
if num == 0:
return 0
return 1 + (num - 1) % 9
public class Solution {
public int AddDigits(int num) {
if (num == 0) return 0;
return 1 + (num - 1) % 9;
}
}
var addDigits = function(num) {
if (num === 0) return 0;
return 1 + (num - 1) % 9;
};
复杂度分析
| 复杂度类型 | 模拟法 | 数学公式法 |
|---|---|---|
| 时间复杂度 | O(log n) | O(1) |
| 空间复杂度 | O(1) | O(1) |