力扣-258. 各位相加

1.题目

题目地址(258. 各位相加 - 力扣(LeetCode))

https://leetcode.cn/problems/add-digits/?envType=study-plan-v2&envId=primers-list

题目描述

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

 

示例 1:

38
2

示例 2:

输入: num = 0
输出: 0

 

提示:

  • 0 <= num <= 231 - 1

 

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

2. 题解

这道题的本质是计算自然数num的数根。
数根又称数字根(Digital root),是自然数的一种性质,每个自然数都有一个数根。对
于给定的目然数,反复将各个位上的数字相加,直到结果为一位数,则该一位数即为原自然数的数根。
计算数根的最直观的方法是模拟计算各位相加的过程,直到剩下的数字是一位数。利用自然数的性质,则能在O(1)的时间内计算数根。

2.1 模拟

思路

就是拆分,求和,再拆分,再求和; 直到只剩下个位数

代码

  • 语言支持:C++

C++ Code:


class Solution {
public:
    int addDigits(int num) {
        while(num >= 10){
            int sum = 0;
            while(num > 0){
                sum += num % 10;
                num /= 10;
            }
            num = sum;
        }
        return num;
    }
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:O(lognum)
  • 空间复杂度:O(1)

2.2 数学方法(拆分-补缺)

思路

假设整数num的十进制表示有n位,从最低位到最高位依次是a0an1
则 num 可以写成如下形式(每一位都分出来个1, 用于构成树根):

num=i=0n1ai×10i=i=0n1ai×(10i1+1)=i=0n1ai×(10i1)+i=0n1ai

i=0时,10i1=0是 9 的倍数;
i是正整数时,10i1是由i位9 组成的整数,也是 9 的倍数。
因此对于任意非负整数i,10i1都是 9 的倍数。由此可得num与其各位相加的结果模 9 同余。
重复计算各位相加的结果果直到结果为一位数时,该一位数即为num的数根,num与其数根模 9 同余。

我们对num分类讨论:
num不是 9 的倍数时,其数根即为num除以 9 的余数。
num是 9 的倍数时:
如果num=0,则其数根是0;
如果num>0 ,则各位相加的结果大于0,其数根也大于0,因此其数根是 9。

细节

根据上述分析可知,当num>0时,其数根的结果在范围[1,9] 内,因此可以想到计算num1除以 9 的余数然后加 1。
由于当num>0时,num10 ,非负数除以 9 的余数一定也是非负数,因此计算num1除以 9 的余数然后加 1 的结果是正确的。

num=0时,num1=1<0 ,负数对 9 取余或取模的结果的正负在不同语言中有所不同。
对于取余的语言,结果的正负和左操作数相同,则num1对 9 取余的结果为-1 ,加 1 后得到结果0,可以得到正确的结果;
对于取模的语言,结果的正负和右操作数相同,则num1对 9 取模的结果的果为 8,加 1 后得到结果 9,无法得到正确的结果,此时需要对num=0的情况专门做处理。

代码

class Solution {
public:
    int addDigits(int num) {
        return (num - 1) % 9 + 1;
    }
};
posted @   DawnTraveler  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示