313. 超级丑数
方法:“多路归并”
思路
-
这道题其实是
264. 丑数 II
的进阶,前者固定使用三个指针,分别对应于 2、3、5,而这道的primes数组长度不固定,因此使用指针数组来对应 primes 的每一个值。 -
第一个丑数一定是 1,而「往后产生的丑数」都是基于「已有丑数」而来(使用「已有丑数」乘上「给定质因数」primes[i] )。具体过程如图所示。
- 显然,我们需要每次取值最小的一个,然后让指针后移(指向下一个丑数),不断重复这个过程,直到找到第 n 个丑数。
- 另外,由于我们每个指针移动和 dp的构造,都是单调递增,因此可以通过与 dp[i-1] 进行比较来实现去重,而无须引用 Set 结构。
代码
class Solution {
public:
long nthSuperUglyNumber(int n, vector<int>& primes) {
int len = primes.size();
// 指针数组
vector<long> ptr(len, 1);
vector<long> dp(n+1, 0);
dp[1] = 1;
for(int i=2;i<=n;++i){
int flag = 0;
dp[i] = primes[0] * dp[ptr[0]];
for(int j=0; j<len; ++j){
long cur = primes[j] * dp[ptr[j]];
if(cur < dp[i]){
flag = j;
dp[i]= cur;
}
}
ptr[flag]++;
// 如果当前值和上一个丑数一样,那么跳过该丑数
if(dp[i] == dp[i-1]) i--;
}
return dp[n];
}
};