持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情
题目(Ugly Number II)
链接:https://leetcode-cn.com/problems/ugly-number-ii
解决数:877
通过率:58.9%
标签:哈希表 数学 动态规划 堆(优先队列)
相关公司:bytedance amazon google
给你一个整数 n ,请你找出并返回第 n 个 丑数 。
丑数 就是只包含质因数 2、3 和/或 5 的正整数。
示例 1:
输入: n = 10
输出: 12
解释: [1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。
示例 2:
输入: n = 1
输出: 1
解释: 1 通常被视为丑数。
提示:
1 <= n <= 1690
思路
丑数的递推性质: 丑数只包含因子 2,3,5,因此有
“丑数 = 某较小丑数 * 某因子”(例如 10 = 5 * 2)
dp[i + 1] = Math.min(dp[a] * 2, dp[b] * 3, dp[c] * 5 )
代码
/**
* @param {number} n
* @return {number}
*/
var nthUglyNumber = function(n) {
/*
丑数的递推性质: 丑数只包含因子 2,3,5,因此有
“丑数 = 某较小丑数 * 某因子”(例如 10 = 5 * 2)
dp[i + 1] = Math.min(dp[a] * 2, dp[b] * 3, dp[c] * 5 )
*/
let a = b = c = 0, // a b c 分为为对应取因子 2 3 5的索引下标
n2, n3, n5, min
const dp = [1, ...new Array(n - 1)]
for (let i = 1; i < n; i++) {
n2 = dp[a] * 2, n3 = dp[b] * 3, n5 = dp[c] * 5,
min = Math.min(n2, n3, n5)
dp[i] = min
if (min === n2) a++
if (min === n3) b++
if (min === n5) c++
}
return dp[n - 1]
};
思路2
三指针法 因为每个数字都要被计算三次,一次是乘以二,一次是乘以三,一次是乘以5 所以定义三个指针,p_2, p_3, p_5, 这三个指针的起点是一样的,都是0, 如果当前的数字是乘以3得到的,就将p_3向前移动, 如果当前的是乘以2得到的,就将p_2向前移动, 如果当前的是乘以5得到的,就将p_5向前移动
var nthUglyNumber = function(n) {
let dp = [1];
let p_2 = 0;
let p_3 = 0;
let p_5 = 0;
while(dp.length < n){
let now = Math.min(Math.min(dp[p_2] * 2, dp[p_3] * 3), dp[p_5] * 5);
if(now == dp[p_2] * 2){
p_2++;
}
if(now == dp[p_3] * 3){
p_3++;
}
if(now == dp[p_5] * 5){
p_5++;
}
dp.push(now);
}
return dp[n-1];
};