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)

相关题目