Leetcode 面试题49.丑数【优先队列|动态规划】

问题描述

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

解题报告

由于丑数 包含质因子2,3,5,因此较大的丑数可以由较小的丑数依次乘以上述质因子得到。

优先队列

同时构建一个优先队列和集合。
每次从队列中取出一个最小的数,将这个数依次乘以三个因子,然后判断三个新得的三个数是否在集合中,如果不在集合中,则将它们插入集合中以及压入优先队列中,最后将取出的那个数从队列中弹出。

动态规划

d p [ i ] = m i n ( d p [ j 2 ] 2 , d p [ j 3 ] 3 , d p [ j 5 ] 5 ) dp[i]=min(dp[j2]*2,dp[j3]*3,dp[j5]*5) ,所以我们持续更新 三个索引: j 2 j 3 j 5 j2、j3、j5
更新方法是:
判断 d p [ j 2 ] 2 , d p [ j 3 ] 3 , d p [ j 5 ] 5 dp[j2]*2,dp[j3]*3,dp[j5]*5 谁最小,则将对应的索引往后移一位。
思想是:对于一系列顺序生成的丑数,它们是前面的丑数依次乘以三个质因子中的一个生成的。
以质因子2的索引为例:一个丑数乘以2之后,下一次乘以2必定是该丑数的下一个丑数,也即对应的索引加一。

实现代码

优先队列

class Solution {
    public:
        int nthUglyNumber(int n) {
        priority_queue<long long,vector<long long>, greater<long long>> pq;
        set<long>s;
        long long factor[3]={2, 3, 5},ans=1;
        for (int i=0;i<3;i++) {
            pq.push(factor[i]);
            s.insert(factor[i]);
        }
        for (int i = 1; i < n; i++) {
            ans = pq.top();
            pq.pop();
            for (int j = 0; j < 3; j++) {
                if (s.find(ans * factor[j])==s.end()) {
                    pq.push(ans * factor[j]);
                    s.insert(ans * factor[j]);
                }
            }
        }
        return (int)ans;
    }
};

动态规划

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

参考资料

[1] Leetcoed 面试题49.丑数
[2] 题解区:Jerry

MD_
发布了139 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_27690765/article/details/105381884