[LeetCode264.丑数 II] | 刷题打卡

210 阅读2分钟

题目解析:

编写一个程序,找出第 n 个丑数。

丑数就是只包含质因数 2, 3, 5 的正整数。

示例

示例 1:

    输入: n = 10
    输出: 12
    解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

提示:

    1 是丑数。
    n 不超过1690。

解题思路

方法一暴力循环(毫无疑问超时了)

解答

var isUgly = function(num) {
    if (num < 1) {
        return false;
    }
     while(num % 2 == 0) {
             num/=2
         } 
     while(num % 3 == 0) {
             num/=3
         } 
     while(num % 5 == 0) {
             num/=5
         }
    
    return (num == 1) ? true : false;
};
    var nthUglyNumber = function(n) {
    var ugly = 1;
    for (var i = 0; i < n; ugly++) {
        if (isUgly(ugly)) {
            i++;
        }
    }
    return ugly;
};

解题思路二

1. 根据题目的意思,我们首先知道丑数的因子只能是(2, 3, 5).
当我们要从[1],推算出[1,2,3,4,5,6,8,9...]丑数序列时,过程如下


var arr = [1]; 
推算第二个数:比较arr[0]*2 和 arr[0]*3 和arr[0]*5 中取最小的一个arr[0]*2
放进数组中: [1, arr[0]*2]。
依次类推下次比较:arr[1]*2 和 arr[0]*3 和 arr[0]*5 中取最小arr[0]*3
放进数组中: [1, arr[0]*2, arr[0]*3]
依次类推下次比较:arr[1]*2 和 arr[1]*3 和 arr[0]*5 中取最小arr[1]*2
放进数组中: [1, arr[0]*2, arr[0]*3, arr[1]*2]
等等。。


2. 由上可以看出,我们需要丑数组arr, 还有2,3,5三个质因数分别乘到了arr的第几个数。
拿2作例子:我们需要知道数组的前多少个已经乘过2了。当arr[0]*2 之后,
下次就该arr[1]*2跟其他的作比较了。

即这2,3,5需要三个标记。在上面举例中第三次之后的下标为:[2, 1, 0].
即下次比较应该用arr[2]*2 和 arr[1]*3 和arr[0]*5 来比较哪个小。

3. 中间会遇到比如 arr[2]*2 == arr[1]*3 这样的情况。
此时把2,3 的下标都+1即可.

最后依次求到目标数组arr的第n个数即为答案。

解答二

var nthUglyNumber = function(n) {
    var arr = [1], indexArr = [0, 0, 0],v2,v3,v5,temp;
    for(var i = 0; i <= n; i++) {
        v2 = arr[indexArr[0]] * 2;        
        v3 = arr[indexArr[1]] * 3;
        v5 = arr[indexArr[2]] * 5;
        temp = Math.min(v2,Math.min(v3,v5)); // 判断最小
        if (temp == v2) {
            indexArr[0]++;
        }
        if (temp == v3) {
            indexArr[1]++;
        }
        if (temp == v5) {
            indexArr[2]++;
        }
        arr.push(temp);
    }
    return arr[n-1];
};

总结

我们在解题国过程中,也许第一种办法都比较笨,可能会超时,但是其实它是最符合自身的思维逻辑的。只有想出第一种自己的办法,我们再使用技巧算法解题,才能理解使用方法解题带来的优势。


本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情