一、题目描述
给定一个非负整数 num
,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。
示例 1:
输入: num =38
输出: 2 解释: 各位相加的过程为: 38 --> 3 + 8 --> 11 11 --> 1 + 1 --> 2 由于2
是一位数,所以返回 2。
示例 2:
输入: num = 0 输出: 0
提示:
0 <= num <= 2^31 - 1
二、解题思路
这个问题通常被称为“数字根”问题。可以通过不断将数字的每一位相加,直到结果为一位数来解决这个问题。但是,这个方法虽然直观,但不是最高效的方法。实际上,存在一个数学规律,即“数字根”可以通过一个简单的公式直接计算得到,这个公式是:
数字根 = 1 + (num - 1) % 9
这个公式的原理基于模9的性质,因为一个数字的各位数之和模9等于该数字本身模9。下面是这个公式的推导:
设 num = a * 10^m + b * 10^(m-1) + … + z,其中 a, b, …, z 是 num 的各个位上的数字。
那么 num 可以表示为 num = a + b + … + z + 9 * (some other number),这里 9 * (some other number) 是由 num 的各位数中的 10 的幂次方部分组成,它们都是 9 的倍数。
因此,num 模 9 等于 (a + b + … + z) 模 9,这意味着我们只需要关注各位数字之和。
根据这个规律,我们可以直接计算出数字根。
三、具体代码
class Solution {
public int addDigits(int num) {
if (num == 0) return 0;
return 1 + (num - 1) % 9;
}
}
这段代码首先检查 num 是否为 0,如果是,直接返回 0。否则,使用上面提到的公式来计算数字根。由于 num 可能为 0,所以需要对 num - 1 进行操作,以避免当 num 为 9 的倍数时结果为 0 的情况。
四、时间复杂度和空间复杂度
1. 时间复杂度
- 该算法中,
addDigits
函数只包含了一个简单的数学运算,不涉及循环或递归调用。 - 无论输入的
num
的大小如何,这个函数的执行时间都是恒定的,即它执行的操作次数不随输入num
的大小而变化。 - 因此,该算法的时间复杂度为 O(1),也称为常数时间复杂度。
2. 空间复杂度
- 在
addDigits
函数中,除了输入参数num
和返回值之外,没有使用额外的数据结构(如数组、链表、哈希表等)来存储数据。 - 该函数只使用了几个变量来执行计算,而这些变量占用的空间大小不随输入
num
的大小而变化。 - 因此,该算法的空间复杂度为 O(1),也称为常数空间复杂度。
五、总结知识点
-
类定义(Class Definition):
class Solution { ... }
: 定义了一个名为Solution
的类。
-
方法定义(Method Definition):
public int addDigits(int num) { ... }
: 在Solution
类中定义了一个名为addDigits
的公共方法,该方法接受一个整数类型的参数num
并返回一个整数。
-
条件语句(Conditional Statement):
if (num == 0) return 0;
: 使用了if
语句来检查num
是否等于 0。如果是,则直接返回 0。
-
算术运算(Arithmetic Operations):
return 1 + (num - 1) % 9;
: 使用了加法(+
)、减法(-
)和取模(%
)运算符来计算数字根。
-
模运算(Modulo Operation):
(num - 1) % 9
: 取模运算符%
用于计算num - 1
除以 9 的余数,这是数字根算法的核心。
-
返回语句(Return Statement):
return 0;
: 在条件满足时返回 0。return 1 + (num - 1) % 9;
: 计算并返回数字根的结果。
-
整型(Integer Type):
int num
: 定义了一个整型变量num
作为方法的参数。return 1 + (num - 1) % 9;
: 返回值也是整型。
-
数学公式应用(Mathematical Formula Application):
- 数字根的计算使用了数学上的一个特性,即一个数减去它的各位数字之和,再对9取模,得到的结果是相同的。这个特性简化了算法的实现。
-
常量(Constant):
0
和9
在这个上下文中被视为常量,用于特定的条件检查和计算。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。