Skip to content
本页目录

49-丑数

题目描述

https://leetcode.cn/problems/chou-shu-lcof/

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

示例:

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

说明:

1 是丑数。
n 不超过1690。

注意:本题与主站 264 题相同:https://leetcode.cn/problems/ugly-number-ii/

思路分析

参考 LeetCode 原题 0264-丑数II

为什么要使用3指针? 不难发现,一个丑数总是由前面的某一个丑数 x3 / x5 / x7 得到。 反过来说也是一样的,一个丑数 x3 / x5 / x7 就会得到某一个更大的丑数。

如果把丑数数列叫做 ugly[i],那么考虑一下三个数列:

1. ugly[0]*3,ugly[1]*3,ugly[2]*3,ugly[3]*3,ugly[4]*3,ugly[5]*3……
2. ugly[0]*5,ugly[1]*5,ugly[2]*5,ugly[3]*5,ugly[4]*5,ugly[5]*5……
3. ugly[0]*7,ugly[1]*7,ugly[2]*7,ugly[3]*7,ugly[4]*7,ugly[5]*7……

上面这个三个数列合在一起就形成了新的、更长的丑数数列。

如果合在一起呢?这其实就是一个合并有序线性表的问题。

定义三个index 分别指向上面三个数列,下一个丑数一定是三个 index 代表的值中最小的那个。然后相应 index++ 即可。

举个例子 初始值 ugly[0]=1; index1=0; index2=0; index3=0

ugly[1]=Min(ugly[index1]*3,ugly[index2]*5,ugly[index3]*7)
=Min(1*3,1*5,1*7)
=3
于是 index1++;

ugly[2]=Min(ugly[index1]*3,ugly[index2]*5,ugly[index3]*7)
=Min(3*3,1*5,1*7)
=5
于是 index2++;

实现代码

csharp
public class Solution {
    public int NthUglyNumber(int n) {
        int[] dp = new int[n+1];
        dp[1] = 1;
        //定义三个指针 p2,p3,p5,下一个数就是前面指针对应乘积最小的数,乘完之后,指针下移
        int p2 = 1;
        int p3 = 1;
        int p5 = 1;
        for(int i=2; i<=n; i++){
            int num2 = dp[p2] * 2;
            int num3 = dp[p3] * 3;
            int num5 = dp[p5] * 5;
            int num = Math.Min(Math.Min(num2,num3),num5);
            if(num == num2){
                p2++;
            }
            if(num == num3){
                p3++;
            }
            if(num == num5){
                p5++;
            }
            dp[i] = num;
        }
        return dp[n];
    }
}

复习:20220508

csharp
public class Solution {
    public int NthUglyNumber(int n) {
        int[] dp = new int[n+1];
        dp[1] = 1;
        //丑数都是 2,3,5的倍数,定义三个指针,然后对该出的丑数 dp[i] *2 , *3, *5 取最小值继续
        int p2 = 1;
        int p3 = 1;
        int p5 = 1;
        for(int i=2; i<=n; i++){
            int num2 = dp[p2] * 2;
            int num3 = dp[p3] * 3;
            int num5 = dp[p5] * 5;
            int num = Math.Min(num2,Math.Min(num3,num5));
            Console.WriteLine("num2={0},num3={1},num5={2},num={3}",num2,num3,num5,num);
            if(num2 == num){
                p2++;
            }
            if(num3 == num){
                p3++;
            }
            if(num5 == num){
                p5++;
            }
            dp[i] = num;
        }
        return dp[n];
    }
}

Released under the MIT License.