2 模拟
258. 各位相加 ★
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。
示例 1:
输入: num = 38
输出: 2
解释: 各位相加的过程为:
38 --> 3 + 8 --> 11
11 --> 1 + 1 --> 2
由于 2 是一位数,所以返回2。
示例 2:
输入: num = 0
输出: 0
算法设计
这道题的本质是计算自然数num的数根。数根又称数字根(Digital root),是自然数的一种性质,每个自然数都有一个数根。对于给定的自然数,反复将各个位上的数字相加,直到结果为一位数,则该一位数即为原自然数的数根。
1.模拟法
计算数根的最直观的方法是模拟计算各位相加的过程,直到剩下的数字是一位数。
算法实现:
//LeetCode258 各位相加
int addDigits(int num) {
while (num > 9){ // num为两位数
int ans = 0; // 累加各个位的和值
while (num) {
ans += num % 10;
num /= 10;
}
num = ans; // 将各位和赋值给num,继续循环
}
return num;
}
2.数学法
利用自然数的性质,则能在O(1)的时间内计算数根。
假设整数num有n位,从最低位到最高位依次是a0…a**n−1,则num可以写成如下形式:
由此可得num与其各位相加的结果模9同余。
- num=0,其数根是0;
- num是9的倍数,其数根是9;
- num不是9的倍数,其数根是num除以9的余数。
算法实现:
int addDigits(int num) {
if num == 0:
return 0;
if num % 9 == 0:
return 9;
return num % 9;
}
实际上,num与其各位相加的结果模9同余,无需分情况判断,直接计算(num - 1) % 9 + 1即可,结果相同。
算法实现:
int addDigits(int num) {
return (num - 1) % 9 + 1;
}
算法分析:
模拟算法的时间复杂度为O(logn),数学法的时间复杂度为O(1)。空间复杂度均为O(1)。