313. Super Ugly Number

思路:

这个题也可以用堆来做,和题313. Super Ugly Number的 堆做法一样。
通过大顶堆,即降序的堆来存放每个数,初始化res为1,因为这里的丑数的质因数只能是数组primes里面的,所以只要将2,3,5改为primes里的数即可。
在判断堆里是否有重复的元素,有则pop掉。

代码:

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        priority_queue<double,vector<double>,greater<double>> pq;
        double res=1;
        for(int i=1;i<n;++i){
            for(auto& prime:primes){  //将res*2,*3,*5改为*primes里的数
                pq.push(res*prime);
            }
            res=pq.top(); pq.pop();
            while(!pq.empty()&& res==pq.top()) pq.pop(); 
        }
        return res;
    }
};

动态规划

同样这题也和331题相似,但是这里的质因数是动态的,所以我们可以定义一个数组来做指针,指针的个数和质因数的个数相同。然后就是dp的数组,确保dp[0]为1,
然后进入一个n-1次循环,因为我们是先排序的,所以确保了是递增的那么只要n-1次循环即可得到第n个丑数。然后定义一个M=INT_MAX,因为我们要取最小的dp[p[j]]*primes[j]的值,即这次循环的最小的丑数,指针指哪个地方说明这个地方要乘上这个指针代表的质因数。找到该次最小丑数后,加入进dp数组里面,然后循环再找到是哪个指针指向的dp[p[j]],说明这个指针的作用完成就右移。
代码:

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        int k=primes.size();
        vector<int> p(k,0);  //K个指针
        vector<int> dp(1,1);
        for(int i=1;i<n;++i){
            int m=INT_MAX;
            for(int j=0;j<k;++j){
                m=min(m,dp[p[j]]*primes[j]);
            }
            dp.push_back(m);
            for(int j=0;j<k;++j){
                if(dp[i]==dp[p[j]]*primes[j])
                    p[j]++;
            }
        }
        return dp[n-1];
    }
};
posted @ 2021-04-07 20:04  Mrsdwang  阅读(35)  评论(0编辑  收藏  举报