[路飞]_leetcode-313-超级丑数

135 阅读1分钟

题目描述

[题目地址]

超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 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 <= 106
  • 1 <= primes.length <= 100
  • 2 <= primes[i] <= 1000
  • 题目数据 保证 primes[i] 是一个质数
  • primes 中的所有值都 互不相同 ,且按 递增顺序 排列

分析

本题与上一题 leetcode-264-丑数 II 类似, 区别在于上题中质因数是确定的 235,而本题中质因数是通过数组参数传递进来的,但是解题思路是相同的。接下来我们以质因数 235 为例,讲解求得第 n 个丑数的过程。

要求得第 n 个丑数,首先要明确什么是丑数?
丑数的定义:只包含质因数 23 和/或 5 的正整数。

基于以上条件,我们将已经得到的丑数分别和质因数 235 相乘,就得到了后续的丑数
因为 1 是第一个丑数,所以基于以上逻辑可以得到这样的结果。

1 2 3 5 4 6 10 6 9 15 10 15 25 8 12 20 ...
2 3 5

但是上面的结果序列有两个问题:

  1. 序列并不是有序的
  2. 存在重复的值

那如何在求得所有丑数的过程中避免以上两个问题呢?

  1. 初始化结果数组并插入第一个元素 1
  2. 定义三个质因数的指针,初始化指向下标 0
  3. 求得每个质因数和其对应指针在结果数组中对应值的乘积
  4. 获取所有乘积中的最小值,该值即下一个丑数
  5. 将最小值对应的质因数的指针向后移动一位
  6. 重复以上过程,直到求得第 n 个丑数

通过以上的过程,保证了求得丑数是严格升序排列的。当多个质因数的乘积有相同的最小值时,将对应质因数指针都向后移动一位,这样就保证了不会有重复的结果。

了解了基于质因数 235求解丑数的过程,只需要把对应质因数换成 primes 数组即可完成本题。

动画演示

leetcode-264-丑数 II.gif 动画转自奔跑的蜗牛

代码实现

var nthSuperUglyNumber = function(n, primes) {
    const res = [1];
    const points = new Array(primes.length).fill(0)//创建一个数组,赋值
    let min,map;
    for(let i = 1; i< n;i++){
        map = primes.map((prime,index)=>
            res[points[index]] * prime
        )
        min = Math.min.apply(null,map);//求最小值
        // 去重
        primes.forEach((prime,index)=>{
            if(map[index] === min) points[index]++;
        })
        res.push(min)
    }
    return res[n-1];
};

至此我们就完成了 leetcode-313-超级丑数