题目传送
思路:
递推,dp
每次选取一个最小臭数,dp【i】,但是最重要的如何维护,使得每次精准求出第i个丑数。
1.那么第一个丑数必定是1
2.第二个丑数,则需要借助前面的丑数来进行计算。现在令pos数组全为0,我们可以想想,我们用每一个质数来乘以它当前能乘的最小丑数(重复的和已经计算过的除外)。那么pos数组则对应每一个质数能乘的最小丑数(肯定是先乘最小的才能维护到准确的第i个丑数呀)
3.那么pos还要进行相应的处理。当选中了准确的第i个丑数后。那么对应的那个质数所能乘的最小丑数又要变化了,我们令pos【j】++,代表选中下一个可乘丑数
关键思路已经说了,看懂代码最重要。
AC代码
class Solution {
public:
int nthSuperUglyNumber(int n, vector<int>& primes) {
int dp[1000005] = {0},pos[10005] = {0}; //pos代表每一个质数所对应的可乘最小丑数
dp[0] = 1; //第一个丑数必定为1
for(int i = 1;i < n;i++) //接下来每次维护吃第i个丑数
{
long long Min = 1e18 + 7; //维护出最小值
for(int j = 0;j < primes.size();j++) //枚举每一个质数
{
Min = min(Min,(long long)(primes[j]*dp[pos[j]]));
//primes[j]代表第j个质数
//pos[j] 代表这个质数所能乘的最小丑数的位置
}
dp[i] = Min; //维护成功
for(int j = 0;j < primes.size();j++) //去掉重复的,
{
if(dp[i] == primes[j]*dp[pos[j]]) //找到重复的,也可以说找到刚刚枚举到的那个质数
{
pos[j]++; //可乘最小丑数变了,变成其下一个
}
}
}
return dp[n-1];
}
};