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];
}
};