网络异常,图片无法展示
|
超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 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 类似, 区别在于上题中质因数是确定的 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 arr = Array(n).fill(1), len = primes.length, // 创建质因数指针 inds = Array(len).fill(0), // 创建质因数与指针值乘积结果数组 nums = [...primes]; // 遍历求解每一个丑数 for(let i = 1;i<n;i++){ // 获取乘积最小值 const min = Math.min(...nums); // 更新当前位置丑数 arr[i] = min; // 更新质因数指针及质因数与指针值乘积结果 for(let j = 0;j<len;j++){ if(min === nums[j]){ inds[j]++; nums[j] = arr[inds[j]]*primes[j] } } } // 返回第n个丑数 return arr[n-1] }; 复制代码
至此我们就完成了 leetcode-313-超级丑数
如有任何问题或建议,欢迎留言讨论!