Skip to main content

313.超级丑数

标签: heap, math

难度: Medium

通过率: 45.39%

原题链接: https://leetcode.com/problems/super-ugly-number/description/

题目描述

超级丑数是一个正整数,其所有的质因子都在给定的质数数组 primes 中。给定一个整数 n 和一个整数数组 primes,返回第 n 个超级丑数。

解题思路

我们可以使用多指针法加堆实现来求解这个问题。思路是维护一个堆用于存储当前的超级丑数,并通过不断从堆中取出最小的数来生成下一个超级丑数:

  1. 初始化一个数组 ugly,其中 ugly[0] = 1(第一个超级丑数总是 1)。
  2. 使用堆来维持当前的超级丑数。我们使用元组 (值, 指数, 索引) 存储,索引标识使用的质数。
  3. 对每个质数 p,我们将 (p, 0, index_p) 放入堆,其中 index_pp 在 primes 中的索引。
  4. 从堆中不断取出最小的元素,依次填充 ugly 数组。对于每个从堆中取出的元素 (value, i, index_p),我们将值写入数组,并将 (primes[index_p] * ugly[i+1], i+1, index_p) 插入堆。
  5. 当我们填充完 ugly[n-1] 时,我们就得到了第 n 个超级丑数。

代码实现

import heapq  # 引入堆

def nthSuperUglyNumber(n: int, primes: List[int]) -> int:
ugly = [1] * n # 初始化超级丑数数组
heap = [(prime, 0, prime) for prime in primes] # 初始化堆 (当前值, 索引, 质数)
heapq.heapify(heap)
for i in range(1, n):
ugly[i] = heap[0][0] # 取堆顶的值作为下一个超级丑数
while heap and heap[0][0] == ugly[i]:
val, idx, prime = heapq.heappop(heap) # 弹出堆顶
heapq.heappush(heap, (prime * ugly[idx + 1], idx + 1, prime))
return ugly[-1]

复杂度分析

时间复杂度:O(nlogk)O(n \log k),其中 nn 是我们要求的超级丑数的个数,kk 是质数数组的长度,因为我们使用了堆来维持当前的超级丑数。

空间复杂度:O(n+k)O(n + k),用于存储超级丑数的数组和堆。