美文网首页
2020-06-02 归并 264. Ugly Number I

2020-06-02 归并 264. Ugly Number I

作者: 苦庭 | 来源:发表于2020-06-03 05:59 被阅读0次

https://leetcode.com/problems/ugly-number-ii
参考:https://www.cnblogs.com/grandyang/p/4743837.html

My answer / NAC

/**
 * @param {number} n
 * @return {number}
 */
var nthUglyNumber = function(n) {
    if(n==1) return 1;
    var merged=[], dp1 = [], dp2 = [], dp3 = [];
    dp1[0] = 2;
    dp2[0] = 3;
    dp3[0] = 5;
    for(let i=1; i<=1960; i++){
        dp1[i*3-2]=dp1[i-1]*2;
        dp1[i*3-1]=dp1[i-1]*3;
        dp1[i*3]=dp1[i-1]*5;
        
        dp2[i*3-2]=dp2[i-1]*2;
        dp2[i*3-1]=dp2[i-1]*3;
        dp2[i*3]=dp2[i-1]*5;
        
        dp3[i*3-2]=dp3[i-1]*2;
        dp3[i*3-1]=dp3[i-1]*3;
        dp3[i*3]=dp3[i-1]*5;
        
        merged = merge(dp1, dp2, dp3);
        
    }

    return merged[n-1];
};

var merge = function(a1, a2, a3) {
    return Array.from(new Set(a1.concat(a2, a3, [1]))).sort((a,b)=>a-b);
}

想出来了办法但是总是超时,卡在栈的优化处理上了。

Best answer

/**
 * @param {number} n
 * @return {number}
 */
var nthUglyNumber = function(n) {
    if(n==1) return 1;
    var merged=[1], i2=0, i3=0, i5=0;
    while(merged.length<n){
        var m2 = merged[i2]*2, m3 = merged[i3]*3, m5 = merged[i5]*5;
        var mn = Math.min(m2, Math.min(m3, m5));
        if(mn===m2) ++i2;
        if(mn===m3) ++i3;
        if(mn===m5) ++i5;
        merged.push(mn);

    }
    return merged.pop();
};

好在哪?

  • 方法就是用如下3个子列表,3个变量存储答案数组merged的3个暂时的位置,代表乘数为2、3、5当前的被乘数的位置(因为丑陋数必须是由丑陋数乘2/3/5产生)。只有当前算出来的数是最小的才自增1并加进去答案的数组里,否则保持不变。m2 = merged[i2] * 2 意思是当前属于乘数为2的丑陋数m2(下表的第一列,随后是乘数为3、5的丑陋数)。

(1) 1x2, 2x2, 2x2, 3x2, 3x2, 4x2, 5x2...
(2) 1x3, 1x3, 2x3, 2x3, 2x3, 3x3, 3x3...
(3) 1x5, 1x5, 1x5, 1x5, 2x5, 2x5, 2x5...

  • 每次只有你是最小的(加粗的)你才会自增,否则保持当前被乘数位置。

Recap

了解到了一种船新的思路,被乘数位置表示的是当前所能取的最大值了(要等别的两个被乘数位置都超过我了,我才有机会再往上走,这样就不会漏掉丑陋数),利用三个变量来各自表示当前所到达的被乘数位置。

相关文章

网友评论

      本文标题:2020-06-02 归并 264. Ugly Number I

      本文链接:https://www.haomeiwen.com/subject/qzryzhtx.html