• 面试题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/

    ----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
  • 相关阅读:
    map方法,以及filter方法的使用
    detach与remove区别,以及detach保留被删除的元素数据,使用
    jQuery 文档操作
    javascript 清空数组的方法
    jquery遍历数组的方式
    Oracle表空间不足处理
    css 文本超出2行就隐藏并且显示省略号
    Vim中的寄存器
    spacemacs怎样配置编辑器显示行号?
    Docker考前突击
  • 原文地址:https://www.cnblogs.com/wzw0625/p/12742605.html
Copyright © 2020-2023  润新知