Redian新闻
>
LeetCode 力扣官方题解 | 258. 各位相加

LeetCode 力扣官方题解 | 258. 各位相加

公众号新闻

258. 各位相加(点击文末阅读原文查看题目)

题目描述

难易度:简单


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

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


示例 2:

输入: num = 0输出: 0


提示:

  • 0 <= num <= 231 - 1


解决方案


前言

这道题的本质是计算自然数 num 的数根。

数根又称数字根(Digital root),

是自然数的一种性质,每个自然数都有一个数根。对于给定的自然数,反复将各个位上的数字相加,直到结果为一位数,则该一位数即为原自然数的数根。


计算数根的最直观的方法是模拟计算各位相加的过程,直到剩下的数字是一位数。利用自然数的性质,则能在 O(1) 的时间内计算数根。


方法一:模拟


思路和算法


最直观的方法是模拟各位相加的过程,直到剩下的数字是一位数。

计算一个整数的各位相加的做法是,每次计算当前整数除以 10 的余数得到最低位数,将最低位数加到总和中,然后将当前整数除以 10。重复上述操作直到当前整数变成 0,此时的总和即为原整数各位相加的结果。



代码


Java

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;    }}


C#

public 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;    }}


C++

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;    }};


C

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


JavaScript

var addDigits = function(num) {    while (num >= 10) {        let sum = 0;        while (num > 0) {            sum += num % 10;            num = Math.floor(num / 10);        }        num = sum;    }    return num;};


Python3

class Solution:    def addDigits(self, num: int) -> int:        while num >= 10:            sum = 0            while num:                sum += num % 10                num //= 10            num = sum        return num


Golang

func addDigits(num int) int {    for num >= 10 {        sum := 0        for ; num > 0; num /= 10 {            sum += num % 10        }        num = sum    }    return num}


复杂度分析

  • 时间复杂度:O(log num),其中 num 是给定的整数。对于 num 计算一次各位相加需要 O(log num) 的时间,由于 num ≤ 231 - 1,因此对于 num 计算一次各位相加的最大可能结果是 82,对于任意两位数最多只需要计算两次各位相加的结果即可得到一位数。

  • 空间复杂度:O(1)。



方法二:数学

思路和算法


假设整数 num 的十进制表示有 n 位,从最低位到最高位依次是 aan−1则 num 可以写成如下形式:


当 i = 0 时,10- 1 = 0 是 9 的倍数;当 i 是正整数时,10i − 1 是由 i 位 9 组成的整数,也是 9 的倍数。因此对于任意非负整数 i,10i  1 都是 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] 内,因此可以想到计算  num − 1 除以 9 的余数然后加 1。由于当 num > 0 时,num − 1 ≥ 0,非负数除以 9 的余数一定也是非负数,因此计算 num − 1 除以 9 的余数然后加 1 的结果是正确的。


当 num = 0 时,num − 1 = − 1 < 0,负数对 9 取余或取模的结果的正负在不同语言中有所不同。

  • 对于取余的语言,结果的正负和左操作数相同,则 num − 1 对 9 取余的结果为 -1,加 1 后得到结果 0,可以得到正确的结果;

  • 对于取模的语言,结果的正负和右操作数相同,则 num − 1 对 9 取模的结果为 8,加 1 后得到结果 9,无法得到正确的结果,此时需要对 num = 0 的情况专门做处理。


代码

Java

class Solution {    public int addDigits(int num) {        return (num - 1) % 9 + 1;    }}


C#

public class Solution {    public int AddDigits(int num) {        return (num - 1) % 9 + 1;    }}


C++

class Solution {public:    int addDigits(int num) {        return (num - 1) % 9 + 1;    }};


C

int addDigits(int num){    return (num - 1) % 9 + 1;}


JavaScript

var addDigits = function(num) {    return (num - 1) % 9 + 1;};


Python3

class Solution:    def addDigits(self, num: int) -> int:        return (num - 1) % 9 + 1 if num else 0


Golang

func addDigits(num int) int {    return (num-1)%9 + 1}


复杂度分析

  • 时间复杂度:O(1)

  • 空间复杂度:O(1)


BY / 

本文作者:力扣

编辑&版式:Janson

声明:本文归“力扣”版权所有,如需转载请联系。


点个在看,少个 bug

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
2023开年16天上岸谷歌,Leetcode刷题小抄背完,面试真的不一样…LeetCode 力扣官方题解 | 917. 仅仅反转字母背完LeetCode刷题模板,真的不一样!(已拿字节offer)主席让他当部长,他拒绝,主席用车送他回去 (多图)2022傅雷翻译出版奖获奖者揭晓 Le palmarès du Prix Fu Lei 2022 dévoiléLeetCode 力扣官方题解 | 537. 复数乘法Layoff潮,对传统刷LeetCode发起新挑战!气候变化 | IEEE 2023主席Saifur Rahman和IEEE代表团出席COP27LeetCode 力扣官方题解 | 590. N 叉树的后序遍历留学圈疯传!商科生转码《Leetcode刷题指南》,信息量太大拿下6家offer经验分享:刷LeetCode这件事,其实不靠努力!挪威交响诗(九)从盖朗厄尔Geiranger到克里斯蒂安松Kristiansund—又读一页35岁被裁,刷LeetCode变成了自我感动...深度好文|打卡LeetCode的第100天,我才发现......打卡LeetCode的第100天,我才发现......LeetCode 力扣官方题解 | 2016. 增量元素之间的最大差值今天的神笔马良Xcode弃用Bitcode,导致应用体积大幅增加挑战刷最少的题进大厂!不会刷leetcode的人,救星来了商科留学生转码必备:Leetcode到底该怎么刷?LeetCode 力扣官方题解 | 2055. 蜡烛之间的盘子岗位相同,工作5年后,年薪50万和年薪10万的人差距在哪里?LeetCode 力扣官方题解 | 6. Z 字形变换Careers Stalled, China’s Liberal Arts Grads Learn to CodeLeetCode 力扣官方题解 | 521. 最长特殊序列 Ⅰ题都白刷了?Amazon导师亲自为你揭秘LeetCode刷题真相!秋色LeetCode 力扣官方题解 | 2049. 统计最高分的节点数目注意!眼下比刷LeetCode更重要的事中共二十大后的感叹感想Leetcode出题人,揭秘打工体验!发现了《Leetcode刷题指南》,我半年成功转码上岸谷歌亚麻,越来越嫌弃Leetcode刷题家…LeetCode 力扣官方题解 | 2104. 子数组范围和注意!眼下比有刷LeetCode更重要的事…
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。