题目

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。

示例 1:

输入: num = 38
输出: 2
解释: 各位相加的过程为:
38 —> 3 + 8 —> 11
11 —> 1 + 1 —> 2
由于 2 是一位数,所以返回 2。
示例 1:

输入: num = 0
输出: 0

提示:

0 <= num <= 231 - 1

进阶:你可以不使用循环或者递归,在 O(1) 时间复杂度内解决这个问题吗?

思路

最笨的办法肯定是按题意模拟,要写两个循环,时间复杂度和258. 各位相加 - 图1的位数相关,是258. 各位相加 - 图2级别。

想能不能每两位相加后立马再加一次,只保留末位个位数,试了一下也是可以的,比如输入258. 各位相加 - 图3,先加最末尾两位258. 各位相加 - 图4258. 各位相加 - 图5,得到258. 各位相加 - 图6258. 各位相加 - 图7258. 各位相加 - 图8258. 各位相加 - 图9相加得到258. 各位相加 - 图10258. 各位相加 - 图11258. 各位相加 - 图12相加得到258. 各位相加 - 图13258. 各位相加 - 图14258. 各位相加 - 图15258. 各位相加 - 图16得到258. 各位相加 - 图17258. 各位相加 - 图18258. 各位相加 - 图19得到258. 各位相加 - 图20258. 各位相加 - 图21258. 各位相加 - 图22258. 各位相加 - 图23得到258. 各位相加 - 图24,结果和8+7+4+9->28->10->1是一样的。这样只需要一个循环,但复杂度还是一样的。

关于常数时间内求解,确实想不到。评论区的这个解释很明了:258. 各位相加 - 图25#card=math&code=X%20%3D%20100%2Aa%20%2B%2010%2Ab%20%2B%20c%20%3D%2099%2Aa%20%2B%209%2Ab%20%2B%20%28a%2Bb%2Bc%29&id=RNHpx),所以对258. 各位相加 - 图26取余即可。不过如果258. 各位相加 - 图27大于258. 各位相加 - 图28且余数是258. 各位相加 - 图29,要返回258. 各位相加 - 图30

代码

O(logn)

  1. class Solution {
  2. public int addDigits(int num) {
  3. int ans = 0;
  4. while (num > 0) {
  5. ans += num % 10;
  6. num /= 10;
  7. // 这里ans每次算完都是一个10以内的数
  8. ans = ans % 10 + ans / 10;
  9. }
  10. return ans;
  11. }
  12. }

O(1)

  1. class Solution {
  2. public int addDigits(int num) {
  3. if (num <= 9) return num;
  4. num %= 9;
  5. return num == 0 ? 9 : num;
  6. }
  7. }