面试题49:丑数(C++)

题目地址:https://leetcode-cn.com/problems/chou-shu-lcof/

题目描述

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

题目示例

示例:

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

解题思路

首先分析何谓丑数?一个数的因子只包含2,3,5的数称为丑数。数字1特别对待也看作是丑数,所以从1开始的10个丑数分别为1,2,3,4,5,6,8,9,10,12。那么,如何判断一个数是不是丑数呢?我们使用循环冗余法判断,即设待判断整数位N,N循环除以2直到不能整除,此时接着循环除以3直到不能整除,接着循环除以5直到商为1或者不能整除为止。商为1且余数为0则为丑数,否则为非丑数。以12为例,循环除以2,12/2=6,6/2=3,3/2不能整除,转为循环除以3,3/3=1,结束,12为丑数。我们可以发现除了1以外,丑数都是由某个丑数*2或者*3或者*5得到的。如2是丑数1*2得到的,3是丑数1*3得到的,4是丑数1*4得到的,5是丑数1*5得到的,6是丑数2*3得到的……。所以,我们使用动态规划的思想解决。

动态规划:我们设动态规划列表为dp,初始化第一个丑数dp[0]=1,其中dp[i]代表第i+1个丑数,状态转移方程为dp[i]=min(dp[a]*2,min(dp[b]*3,dp[c]*5),最后返回第n个丑数dp[n-1]。每轮计算dp[i]之后,需要更新a、b、c的值,分别独立判断dp[i]与dp[a]*2、dp[b]*3、dp[c]*5的大小是否相等,若相等,则对应的索引a、b、c自增一。

队列:我们使用三个队列q2、q3、q5分别存放当前访问值乘2、乘3、乘5的值,同时在迭代的过程里取出三个队列里最小的作为下轮访问的值,需要注意的是,取出数字的时候需要更新可能的值,为了避免重复插入的情况,比如q2插入了6,q3也插入了6,我们只允许从q2中取出的值乘2、乘3、乘5,q3中取出的值只允许乘3或乘5,q5中取出的值只允许乘5

程序源码

动态规划

class Solution {
public:
    int nthUglyNumber(int n) {
        if(n == 1) return 1;
        int a = 0, b = 0, c = 0;
        vector<int> dp(n);
        dp[0] = 1;
        for(int i = 1; i < n; i++)
        {
            dp[i] = min(dp[a] * 2, min(dp[b] * 3, dp[c] * 5));
            if(dp[i] == dp[a] * 2) a++;
            if(dp[i] == dp[b] * 3) b++;
            if(dp[i] == dp[c] * 5) c++;
        }
        return dp[n - 1];
    }
};

队列

class Solution {
public:
    int nthUglyNumber(int n) {
        if(n == 1) return 1;
        queue<long> q2, q3, q5;
        q2.push(2);
        q3.push(3);
        q5.push(5);
        long res;
        for(int i = 1; i < n; i++)
        {
            long tmp_2 = q2.front();
            long tmp_3 = q3.front();
            long tmp_5 = q5.front();
            res = min(min(tmp_2, tmp_3),tmp_5);
            if(res == tmp_2)
            {
                q2.pop();
                q2.push(res * 2);
                q3.push(res * 3);
                q5.push(res * 5);
            }
            if(res == tmp_3)
            {
                q3.pop();
                q3.push(res * 3);
                q5.push(res * 5);   
            }
            if(res == tmp_5)
            {
                q5.pop();
                q5.push(res * 5);   
            }
        }   
        return res;
    }
};

参考文章

https://leetcode-cn.com/problems/chou-shu-lcof/solution/mian-shi-ti-49-chou-shu-dong-tai-gui-hua-qing-xi-t/

https://blog.csdn.net/my_mao/article/details/24366291

https://leetcode-cn.com/problems/chou-shu-lcof/solution/c-ling-pi-xi-jing-cai-yong-dui-lie-chu-li-by-wfnus/

猜你喜欢

转载自www.cnblogs.com/wzw0625/p/12742605.html