LeetCode 258.各位相加

以下代码如无说明均在力扣上C++语言运行通过

题目描述

题目地址 | 给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。

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

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

题目解答

首先用常规的思路想,肯定是要用到循环的,首先计算出给定数字的各位之和,然后再看得到的结果,如果该结果不为一位数,则继续之前的步骤进行计算,否则退出循环,输出结果。问题的解答步骤可以描述如下:

  1. 计算完数值 num 的各位之和,并存到一个临时变量 temp 中;
  2. 若 temp < 10,则重复第1步;否则退出循环。

代码如下【执行用时:12ms,内存消耗:8.3MB】:

class Solution {
public:
    int addDigits(int num) {
        int temp=0;
        while (num) {
            temp += (num%10);
            num /= 10; // n等于0意味着一轮算完了
            if (num == 0) {
                if (temp < 10) {
                    break;
                } else {
                    num = temp; 
                    temp = 0; // 一定要记得将temp归零
                }
            }
        }
        return temp;
    }
};

上述代码有一个地方需要注意,第13行,一开始我没有加上第13行,这意味着temp每次计算完一轮之后都没有归零,一直在累加上次循环完后的结果,导致程序陷入死循环中。

现在来尝试不用循环解决问题。

我们来分析一下这种变换之后的数字的规律,设 n u m = a b c num = abc num=abc,即 s 1 = 100 a + 10 b + c s1 = 100a+10b+c s1=100a+10b+c,则变换之后, s 2 = a + b + c s2 = a+b+c s2=a+b+c,有 s 1 − s 2 = 99 a + 9 b = 9 ( 11 a + b ) s1-s2=99a+9b=9(11a+b) s1s2=99a+9b=9(11a+b),差值是9的倍数, s 2 s2 s2 s 1 s1 s1去除部分9的倍数之后的结果。若 s 2 s2 s2不为一位数,假设 s 2 = 10 x + y s2=10x+y s2=10x+y,则 s 3 = x + y s3=x+y s3=x+y,有 s 2 − s 3 = 9 x s2-s3=9x s2s3=9x,差值也为9的倍数, s 3 s3 s3 s 2 s2 s2去除部分9的倍数之后的结果。即,每次变换前后的差值都为9的倍数,故最后的结果总为 n u m % 9 ​ num\%9​ num%9

但是,结果为 n u m num%9 num的话,结果明显是小于9的。当num为9的时候,结果明显为9,但是依据我们前面的分析得出来是0。故可以在计算的时候进行判断,如果 n u m % 9 = = 0 num\%9==0 num%9==0,则输出 9 9 9

代码如下【执行用时:16ms,内存消耗:8.4MB】:

class Solution {
public:
    int addDigits(int num) {
        int temp=0;
        if (num>0) {
            temp = num%9;
            if (temp == 0) {
                temp = 9;
            }
        }  
        return temp;
    }
};

也可以直接return回去,一行代码解决【执行用时:16ms,内存消耗:8.3MB】:

class Solution {
public:
    int addDigits(int num) {
        return num==0?0:(num%9==0?9:num%9);
    }
};

事实上,在c++中,三目运算符的运算效率比if…else要低,所以还是尽量少用三目运算符。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值