剑指 Offer 49. 丑数

246 阅读2分钟

「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

  • 我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
示例:

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

说明: 1 是丑数。n 不超过1690。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/chou-shu-lcof

思路

  • 首先我们来观察样例,可以发现出
    • 丑数都是可以由最基础的2,3,5组合而成
    • 比如8 = 2*2*2,12 = 2*2*3....等等
    • 那按照这样的思路我们去想,都以2,3,5为基础
    • 从第一个丑数开始,一个个往后数丑数,并且我们保证丑数是递增的,那么我们求第n个就是想要的答案
    • 那么我们维护三个指针来看2,3,5是命中的哪一个数,再让指针加一

举例

  • 例如 现在n = 10, nums = [2,3,5]

    • 最终打印出来是 1,2,3,4,5,6,8,9,10,12
    • 首先 1是第一位
  • 此刻 n2 = 12 n3 = 13 n5 = 1*5 ,这时我们可以粗略的发现n2,n3,n5三个指针就是初始化一次,接下来的指针移位就能看的更清晰

    • 因为 2 是丑数,所以dp[1]此刻为n2 也就是 2,
    • 那么下面的三个if判断其实就是对一个n2指针进行了加一操作
    • 继续遍历我们能发现 丑数 1,2,3能够求出来
    • 当到了要求丑数为4的时候,我们发现此刻n2 = 4,n3 = 6,n5 = 10,那么dp[3] = 4就求出了
  • 通过上面的例子可以看出,如此的遍历可以得到目标的1,2,3,4,5,6,8,9,10,12

class Solution {
    public int nthUglyNumber(int n) {
        int a = 0,b = 0, c = 0;
        int []dp = new int[n];
        dp[0] = 1;

        for (int i = 1; i< n; i++) {
            int n2 = dp[a] * 2;
            int n3 = dp[b] * 3;
            int n5 = dp[c] * 5;
            dp[i] = Math.min(Math.min(n2,n3),n5);
            
            if (n2 == dp[i]) a++;
            if (n3 == dp[i]) b++;
            if (n5 == dp[i]) c++;
        }
        return dp[n - 1];
    }
}

图片.png