Swift - LeetCode - 各位相加

題目

給定一個(gè)非負(fù)整數(shù) num,反復(fù)將各個(gè)位上的數(shù)字相加,直到結(jié)果為一位數(shù)。返回這個(gè)結(jié)果。

示例 1:

  • 輸入: num = 38
  • 輸出: 2
  • 解釋: 各位相加的過(guò)程為:
    38 --> 3 + 8 --> 11
    11 --> 1 + 1 --> 2
    由于 2 是一位數(shù),所以返回 2。

示例 2:

  • 輸入: num = 0
  • 輸出: 0

前言

這道題的本質(zhì)是計(jì)算自然數(shù) \textit{num} 的數(shù)根。

數(shù)根又稱數(shù)字根(\text{Digital root}),是自然數(shù)的一種性質(zhì),每個(gè)自然數(shù)都有一個(gè)數(shù)根。對(duì)于給定的自然數(shù),反復(fù)將各個(gè)位上的數(shù)字相加,直到結(jié)果為一位數(shù),則該一位數(shù)即為原自然數(shù)的數(shù)根。

計(jì)算數(shù)根的最直觀的方法是模擬計(jì)算各位相加的過(guò)程,直到剩下的數(shù)字是一位數(shù)。利用自然數(shù)的性質(zhì),則能在 O(1) 的時(shí)間內(nèi)計(jì)算數(shù)根。

方法一:模擬

思路及解法

最直觀的方法是模擬各位相加的過(guò)程,直到剩下的數(shù)字是一位數(shù)。

計(jì)算一個(gè)整數(shù)的各位相加的做法是,每次計(jì)算當(dāng)前整數(shù)除以 10 的余數(shù)得到最低位數(shù),將最低位數(shù)加到總和中,然后將當(dāng)前整數(shù)除以 10。重復(fù)上述操作直到當(dāng)前整數(shù)變成 0,此時(shí)的總和即為原整數(shù)各位相加的結(jié)果。

代碼

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

復(fù)雜度分析

  • 時(shí)間復(fù)雜度:O(\log \textit{num}),其中 \textit{num} 是給定的整數(shù)。對(duì)于 \textit{num} 計(jì)算一次各位相加需要 O(\log \textit{num}) 的時(shí)間,由于 \textit{num} \le 2^{31} - 1,因此對(duì)于 \textit{num} 計(jì)算一次各位相加的最大可能結(jié)果是 82,對(duì)于任意兩位數(shù)最多只需要計(jì)算兩次各位相加的結(jié)果即可得到一位數(shù)。

  • 空間復(fù)雜度:O(1)。

方法二:數(shù)學(xué)

思路及解法

假設(shè)整數(shù) \textit{num} 的十進(jìn)制表示有 n 位,從最低位到最高位依次是 a_0a_{n - 1},則 \textit{num} 可以寫成如下形式:

\begin{aligned} \textit{num} &= \sum_{i = 0}^{n - 1} a_i \times 10^i \\ &= \sum_{i = 0}^{n - 1} a_i \times (10^i - 1 + 1) \\ &= \sum_{i = 0}^{n - 1} a_i \times (10^i - 1) + \sum_{i = 0}^{n - 1} a_i \end{aligned}

當(dāng) i = 0 時(shí),10^i - 1 = 09 的倍數(shù);當(dāng) i 是正整數(shù)時(shí),10^i - 1 是由 i9 組成的整數(shù),也是 9 的倍數(shù)。因此對(duì)于任意非負(fù)整數(shù) i10^i - 1 都是 9 的倍數(shù)。由此可得 \textit{num} 與其各位相加的結(jié)果模 9 同余。重復(fù)計(jì)算各位相加的結(jié)果直到結(jié)果為一位數(shù)時(shí),該一位數(shù)即為 \textit{num} 的數(shù)根,\textit{num} 與其數(shù)根模 9 同余。

我們對(duì) \textit{num} 分類討論:

  • num 不是 9 的倍數(shù)時(shí),其數(shù)根即為 \textit{num} 除以 9 的余數(shù)。
  • num9 的倍數(shù)時(shí):
    • 如果 \textit{num} = 0,則其數(shù)根是 0;
    • 如果 \textit{num} > 0,則各位相加的結(jié)果大于 0,其數(shù)根也大于 0,因此其數(shù)根是 9。

細(xì)節(jié)

根據(jù)上述分析可知,當(dāng) \textit{num} > 0 時(shí),其數(shù)根的結(jié)果在范圍 [1, 9] 內(nèi),因此可以想到計(jì)算 \textit{num} - 1 除以 9 的余數(shù)然后加 1。由于當(dāng) \textit{num} > 0 時(shí),\textit{num} - 1 \ge 0,非負(fù)數(shù)除以 9 的余數(shù)一定也是非負(fù)數(shù),因此計(jì)算 \textit{num} - 1 除以 9 的余數(shù)然后加 1 的結(jié)果是正確的。

當(dāng) \textit{num} = 0 時(shí),\textit{num} - 1 = -1 < 0,負(fù)數(shù)對(duì) 9 取余或取模的結(jié)果的正負(fù)在不同語(yǔ)言中有所不同。

  • 對(duì)于取余的語(yǔ)言,結(jié)果的正負(fù)和左操作數(shù)相同,則 \textit{num} - 1 對(duì) 9 取余的結(jié)果為 -1,加 1 后得到結(jié)果 0,可以得到正確的結(jié)果;

  • 對(duì)于取模的語(yǔ)言,結(jié)果的正負(fù)和右操作數(shù)相同,則 \textit{num} - 1 對(duì) 9 取模的結(jié)果為 8,加 1 后得到結(jié)果 9,無(wú)法得到正確的結(jié)果,此時(shí)需要對(duì) \textit{num} = 0 的情況專門做處理。

代碼

class Solution {
    func addDigits(_ num: Int) -> Int {
        return (num - 1) % 9 + 1
    }
}

復(fù)雜度分析

  • 時(shí)間復(fù)雜度:O(1)

  • 空間復(fù)雜度:O(1)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言說(shuō)明 算法學(xué)習(xí),日常刷題記錄。 題目連接 各位相加[https://leetcode-cn.com/probl...
    小鯊魚(yú)FF閱讀 437評(píng)論 0 1
  • 給定一個(gè)非負(fù)整數(shù) num,反復(fù)將各個(gè)位上的數(shù)字相加,直到結(jié)果為一位數(shù)。 示例: 輸入: 38輸出: 2解釋: 各位...
    e8889d737099閱讀 207評(píng)論 0 0
  • 題目描述:給定一個(gè)非負(fù)整數(shù) num,反復(fù)將各個(gè)位上的數(shù)字相加,直到結(jié)果為一位數(shù)。 示例:輸入: 38輸出: 2解釋...
    windUtterance閱讀 589評(píng)論 0 0
  • 題目大意 給定一個(gè)非負(fù)整數(shù) num,反復(fù)將各個(gè)位上的數(shù)字相加,直到結(jié)果為一位數(shù)。示例: 輸入: 38輸出: 2解釋...
    不要甜的紅燒肉閱讀 138評(píng)論 0 0
  • 給定一個(gè)非負(fù)整數(shù) num,反復(fù)將各個(gè)位上的數(shù)字相加,直到結(jié)果為一位數(shù)。 示例: 輸入: 38輸出: 2解釋: 各位...
    simle天晴閱讀 815評(píng)論 0 0

友情鏈接更多精彩內(nèi)容