描述
给出一个非负整数 num
,反复的将所有位上的数字相加,直到得到一个一位的整数。
样例
例1:
输入:
num=38
输出:
2
解释:
过程如下: 3 + 8 = 11, 1 + 1 = 2. 因为 2 只有一个数字,返回 2.
例2:
输入:
num=9
输出:
9
解释:
9<10,返回 9.
挑战
你可以不用任何的循环或者递归算法,在 O(1) 的时间内解决这个问题么?
思路:
这个是官方思路很棒的想法每个大于0的数 他们的倍数都会在【1-9】之间,然后我们取最大的,如果是9的倍数就是0,超过9就进一位,然后我们要把0也算进去所以num>0 得-1让一位 变成num-1>=0,然后得到的mod要+1因为要进一位。以上是我的理解 我贴一下他怎么讲的:
思路和算法
假设整数 \textit{num}num 的十进制表示有 nn 位,从最低位到最高位依次是 a_0a0 到 a_{n - 1}an−1,则 \textit{num}num 可以写成如下形式:
\begin{aligned} \textit{num} &= \sum_{i = 0}^{n - 1} a_i \times 10^i \\ &= \sum_{i = 0}^{n - 1} a_i \times (10^i - 1 + 1) \\ &= \sum_{i = 0}^{n - 1} a_i \times (10^i - 1) + \sum_{i = 0}^{n - 1} a_i \end{aligned}num=i=0∑n−1ai×10i=i=0∑n−1ai×(10i−1+1)=i=0∑n−1ai×(10i−1)+i=0∑n−1ai
当 i = 0i=0 时,10^i - 1 = 010i−1=0 是 99 的倍数;当 ii 是正整数时,10^i - 110i−1 是由 ii 位 99 组成的整数,也是 99 的倍数。因此对于任意非负整数 ii,10^i - 110i−1 都是 99 的倍数。由此可得 \textit{num}num 与其各位相加的结果模 99 同余。重复计算各位相加的结果直到结果为一位数时,该一位数即为 \textit{num}num 的数根,\textit{num}num 与其数根模 99 同余。
我们对 \textit{num}num 分类讨论:
\textit{num}num 不是 99 的倍数时,其数根即为 \textit{num}num 除以 99 的余数。
\textit{num}num 是 99 的倍数时:
如果 \textit{num} = 0num=0,则其数根是 00;
如果 \textit{num} > 0num>0,则各位相加的结果大于 00,其数根也大于 00,因此其数根是 99。
细节
根据上述分析可知,当 \textit{num} > 0num>0 时,其数根的结果在范围 [1, 9][1,9] 内,因此可以想到计算 \textit{num} - 1num−1 除以 99 的余数然后加 11。由于当 \textit{num} > 0num>0 时,\textit{num} - 1 \ge 0num−1≥0,非负数除以 99 的余数一定也是非负数,因此计算 \textit{num} - 1num−1 除以 99 的余数然后加 11 的结果是正确的。
当 \textit{num} = 0num=0 时,\textit{num} - 1 = -1 < 0num−1=−1<0,负数对 99 取余或取模的结果的正负在不同语言中有所不同。
对于取余的语言,结果的正负和左操作数相同,则 \textit{num} - 1num−1 对 99 取余的结果为 -1−1,加 11 后得到结果 00,可以得到正确的结果;
对于取模的语言,结果的正负和右操作数相同,则 \textit{num} - 1num−1 对 99 取模的结果为 88,加 11 后得到结果 99,无法得到正确的结果,此时需要对 \textit{num} = 0num=0 的情况专门做处理。
class Solution:
"""
@param num: a non-negative integer
@return: one digit
"""
def add_digits(self, num: int) -> int:
# write your code here
return (num-1)%9+1 if num else 0