↓快轉到主要內容
  1. LeetCode/

LeetCode 313: Super Ugly Number

·1 分鐘· ·
LeetCode Medium Array Math Dynamic-Programming
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2022-11-16

  • 提交紀錄:Wrong Answer ×2 → Output Limit Exceeded → Accepted → Wrong Answer → Accepted → Output Limit Exceeded → Wrong Answer → Output Limit Exceeded → Wrong Answer

解題思路
#

跟 LC 264 一樣,每個質數 p 有一個指針 idx[p],下一個數是所有 u[idx[p]] * p 的最小值,等於它的指針都前進,O(nk)。

用 heap 的寫法要處理重複:例如 6 會從 2 × 3 和 3 × 2 各被推一次。一個技巧是彈出 x 之後只乘上不超過 x 最小質因數的質數(遇到 x % p == 0 就停),這樣每個數只會被它「最小質因數 × 剩下的部分」產生一次(Heap)。

我的嘗試
#

這題用 heap 寫,錯了 8 次,都跟重複有關:

  • 2022-11-16:彈出 p 後把它乘上每個質數推進去,只在 p == prime 時停,這只有在 p 本身是質數時才會停,像 6 這種合數還是會產生重複,同一個數被彈出兩次,答案往前錯位。
  • 2022-11-26:有幾版拿掉了停止條件,重複更多;把條件改成 p % prime == 0(乘到 p 的最小質因數就停)才 AC。中間還有三次是 print 造成的 Output Limit Exceeded。

正確解法
#

class Solution:
    def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
        u = [1]
        idx = [0] * len(primes)
        while len(u) < n:
            nxt = min(u[idx[k]] * p for k, p in enumerate(primes))
            u.append(nxt)
            for k, p in enumerate(primes):
                if u[idx[k]] * p == nxt:
                    idx[k] += 1
        return u[-1]

複雜度
#

時間 O(nk)(k 是質數個數),空間 O(n + k)。

要特別避免的錯誤
#

  • heap 的寫法沒有去重時,同一個數會被彈出很多次。
  • 去重的停止條件是 x % p == 0(p 是 x 的最小質因數),不是 x == p。

面試口說整理
#

這是 LC 264 的推廣,我讓每個質數有一個指針,指向下一個要乘的醜數,每次取所有乘積的最小值,等於它的指針都前進。時間 O(nk)。用 heap 也可以,但要避免同一個數被推進去很多次。

相關文章

LeetCode 396: Rotate Function
·1 分鐘
LeetCode Medium Array Math Dynamic-Programming
LeetCode 396 解題筆記:F(k) 和 F(k - 1) 只差一個公式:F(k) = F(k - 1) + sum - n × 被移到最前面的那個數
LeetCode 435: Non-overlapping Intervals
·1 分鐘
LeetCode Medium Array Dynamic-Programming Greedy Sorting
LeetCode 435 解題筆記:最少刪幾個 = 總數減掉最多能保留幾個;按右端點排序,貪心保留結束最早的
LeetCode 473: Matchsticks to Square
·1 分鐘
LeetCode Medium Array Dynamic-Programming Backtracking Bit-Manipulation
LeetCode 473 解題筆記:總和要能被 4 整除;由大到小把每根火柴放進四個邊之一,超過邊長或跟前一個邊長度相同就跳過
LeetCode 264: Ugly Number II
·1 分鐘
LeetCode Medium Hash-Table Math Dynamic-Programming Heap-Priority-Queue
LeetCode 264 解題筆記:三個指針分別指向下一個要乘 2、3、5 的醜數,每次取最小的,相等的指針都要前進
LeetCode 189: Rotate Array
·1 分鐘
LeetCode Medium Array Math Two-Pointers
LeetCode 189 解題筆記:先 k %= n,再用三次反轉:整個反轉、前 k 個反轉、後 n - k 個反轉;O(1) 額外空間
LeetCode 204: Count Primes
·1 分鐘
LeetCode Medium Array Math Enumeration Number-Theory
LeetCode 204 解題筆記:埃氏篩,只用質數 p 從 p² 開始把倍數劃掉,外層只要到 √n