「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」
题目介绍
超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 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中的所有值都 互不相同 ,且按 递增顺序 排列
解题思路
本题是 丑数II 的扩展,从 丑数II 的 3 个质因数到不定多个质因数,那么我们解决这道题的方式也和 丑数II 的解决方法类似,只不过从 丑数II 的三指针解法变成多指针解法
我们假设所有符合的丑数都存放在数组 ans 中,那么不在该数组中的数则不是丑数,也就是质因数不止包括 primes 中的数
那么我们用 primes 中的数与 ans 中的任何一个丑数相乘的结果也必然是一个丑数,所以本题的思路就是使用 primes 中的每个值都分别与 ans 中的每一个数相乘,并将结果存放到 ans 数组中
解题步骤
- 定义一个数组
ans,用于存放所有的丑数,ans数组中一开始存放元素 1 - 定义一个数组
p, 用于保存primes长度个指针,每个指针的指向即为每个primes的值需要与之相乘的丑数的位置,每个指针的初始位置都从 0 开始 - 比较每个
primes的值与对应位置的丑数相乘的结果的大小,将最小值插入到ans数组中 - 然后将相乘结果与最小值相等的指针移动到指向下一个丑数的位置
- 重复步骤
3-4n - 1 次,会得到一个包含 n 个丑数的从小到大排序的数组ans - 返回
ans数组的最后一个元素,即为本题的结果
解题代码
var nthSuperUglyNumber = function(n, primes) {
// 定义 ans 数组用于存放所有的丑数
const ans = [1]
// 定义存放指针的数组 p,每个指针的初始值为 0
const p = new Array(primes.length).fill(0)
while (--n) {
let min = Number.MAX_SAFE_INTEGER
// 获取每个质因数与对应位置的丑数相乘结果的最小值
for (let i = 0; i < primes.length; i++) {
min = Math.min(min, primes[i] * ans[p[i]])
}
// 将最小值插入到丑数数组中
ans.push(min)
// 如果相乘结果与最小值相等的,将相应的指针指向下一个丑数
for (let i = 0; i < primes.length; i++) {
if (primes[i] * ans[p[i]] === min) p[i]++
}
}
// 返回第 n 个丑数
return ans[ans.length - 1]
};