LeetCode 258 超通俗讲解:各位相加的两种打开方式

在这里插入图片描述在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
      • 做法一:暴力模拟
      • 做法二:数学法(O(1) 解法)
    • 题解代码分析
      • 方法一:暴力法
      • 方法二:数学法(O(1) 解)
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

这篇文章来聊聊 LeetCode 258 题,题目非常直白——就是给一个非负整数,不停地把它每一位的数字加在一起,直到结果只剩一位数为止。文章将带大家用 Swift 实现两种解法:暴力模拟 + 数学 O(1) 解法,并附上可运行 Demo。

描述

我们要实现一个函数 addDigits(_ num: Int) -> Int,传入一个整数 num,不断把它的每一位相加,直到剩下一位数为止。

举个例子:

输入:38  
过程:3 + 8 = 11,再来 1 + 1 = 2  
输出:2

再比如:

输入:0  
输出:0(本身就是一位数,不用操作)

题解答案

这道题有两种做法:

做法一:暴力模拟

直接按照题意循环,每次都把当前数字的每一位加起来,直到只剩下一位数。

做法二:数学法(O(1) 解法)

这个做法就很巧妙,背后是**数根(digital root)**的概念,有数学公式可以直接算出来一位数。

题解代码分析

方法一:暴力法

func addDigits(_ num: Int) -> Int {
    var n = num
    while n >= 10 {
        var sum = 0
        while n > 0 {
            sum += n % 10
            n /= 10
        }
        n = sum
    }
    return n
}

思路解析

  • while 判断当前是不是一位数,如果不是就不断加每一位;
  • 内部通过取余 % 10 拿到个位数,整除 /= 10 继续处理;
  • 最终当 n 小于 10 的时候,说明只剩一位,直接返回。

方法二:数学法(O(1) 解)

func addDigits(_ num: Int) -> Int {
    if num == 0 { return 0 }
    return num % 9 == 0 ? 9 : num % 9
}

思路解析

  • 除了 0 以外,一个数反复各位相加的结果,其实就是 num % 9
  • 但有个例外:如果 num % 9 == 0,且 num ≠ 0,那返回 9;
  • 这就是数根的原理,可以一行解决,效率爆炸高!

示例测试及结果

print(addDigits(38)) // 输出: 2
print(addDigits(0))  // 输出: 0
print(addDigits(9999)) // 输出: 9
print(addDigits(123456)) // 输出: 3

时间复杂度

  • 方法一(暴力法)

    • 最多也就几轮加法,数值每次都缩小,近似 O(log num)
  • 方法二(数学法)

    • 一行搞定,O(1) 时间复杂度!

空间复杂度

  • 都是 O(1),只用了几个变量。

总结

LeetCode 258 虽然题目简单,但其实挺适合用来理解数学优化思维
暴力法虽然慢一点,但清晰易懂;而数学法则展现出巧妙的数论思想。日常工作中,如果遇到类似“反复计算直到稳定”的问题,这种解题模型是可以借鉴的。

你可能感兴趣的:(Swift,leetcode,算法,职场和发展)