夯实算法-超级丑数

128 阅读1分钟

题目:LeetCode

超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 primes 中。

给你一个整数 n 和一个整数数组 primes ,返回第 n 个 超级丑数 。

题目数据保证第 n 个 超级丑数 在 32-bit 带符号整数范围内。

示例 1:

输入: n = 12, primes = [2,7,13,19]
输出: 32 
解释: 给定长度为 4 的质数数组 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32] 。

示例 2:

输入: n = 1, primes = [2,3,5]
输出: 1
解释: 1 不含质因数,因此它的所有质因数都在质数数组 primes = [2,3,5] 中。

提示:

  • 1<=n<=1051 <= n <= 10^5
  • 1 <= primes.length <= 100
  • 2 <= primes[i] <= 1000
  • 题目数据 保证 primes[i] 是一个质数
  • primes 中的所有值都 互不相同 ,且按 递增顺序 排列

解题思路

根据题意首先对于每一个丑数,要想得到下一个丑数,就用当前的丑数去乘以primes数组中的元素, 得到的最小值就是下一个丑数,刚开始的时候现将1这个丑数构建成一个最小堆,然后将最小堆的根节点去乘以primes数组中的元素,得到的这些元素再次构建最小堆,然后再次取根节点构建最小堆,这样得到的就是所用的丑数列表(注意一个丑数乘以primes里面的这些质因数得到的也是丑数)

代码实现

public int nthSuperUglyNumber(int n, int[] primes) {
    Set < Long > set = new HashSet < > ();
    PriorityQueue < Long > heap = new PriorityQueue < > ();
    set.add(1 L);
    heap.offer(1 L);
    int ugly = 0;
    for (int i = 0; i < n; i++) {
        long cur = heap.poll();
        ugly = (int) cur;
        for (int prime: primes) {
            long tmp = cur * prime;
            if (set.add(tmp)) {
                heap.offer(tmp);
            }
        }
    }
    return ugly;
}

运行结果

Snipaste_2023-02-07_23-05-26.png

复杂度分析

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)  一起分享知识, Keep Learning!