「前端刷题」264.丑数 II(MEDIUM)

79 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

题目(Ugly Number II)

链接:https://leetcode-cn.com/problems/ugly-number-ii
解决数:877
通过率:58.9%
标签:哈希表 数学 动态规划 堆(优先队列) 
相关公司:bytedance amazon google 

给你一个整数 n ,请你找出并返回第 n 个 丑数 。

丑数 就是只包含质因数 23 和/或 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];
};