题目描述
超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 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 <= 1061 <= primes.length <= 1002 <= primes[i] <= 1000- 题目数据 保证
primes[i]是一个质数 primes中的所有值都 互不相同 ,且按 递增顺序 排列
分析
本题与上一题 leetcode-264-丑数 II 类似, 区别在于上题中质因数是确定的 2 、 3 、 5,而本题中质因数是通过数组参数传递进来的,但是解题思路是相同的。接下来我们以质因数 2 、 3 、 5 为例,讲解求得第 n 个丑数的过程。
要求得第 n 个丑数,首先要明确什么是丑数?
丑数的定义:只包含质因数 2、3 和/或 5 的正整数。
基于以上条件,我们将已经得到的丑数分别和质因数 2 、 3 、 5 相乘,就得到了后续的丑数
因为 1 是第一个丑数,所以基于以上逻辑可以得到这样的结果。
1 2 3 5 4 6 10 6 9 15 10 15 25 8 12 20 ...
2 3 5
但是上面的结果序列有两个问题:
- 序列并不是有序的
- 存在重复的值
那如何在求得所有丑数的过程中避免以上两个问题呢?
- 初始化结果数组并插入第一个元素
1 - 定义三个质因数的指针,初始化指向下标
0 - 求得每个质因数和其对应指针在结果数组中对应值的乘积
- 获取所有乘积中的最小值,该值即下一个丑数
- 将最小值对应的质因数的指针向后移动一位
- 重复以上过程,直到求得第
n个丑数
通过以上的过程,保证了求得丑数是严格升序排列的。当多个质因数的乘积有相同的最小值时,将对应质因数指针都向后移动一位,这样就保证了不会有重复的结果。
了解了基于质因数 2 、 3 、 5求解丑数的过程,只需要把对应质因数换成 primes 数组即可完成本题。
动画演示
动画转自奔跑的蜗牛
代码实现
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-超级丑数