set 去除重复
小顶堆是一个元素出来然后存 3 个元素
class Solution {
public:
int nthUglyNumber(int n) {
//因为int 太小容易超出范围 改用long
set<long> s;//set是有序的,且互不重复
long answer=1;//初始化第一个数
for(int i=1;i<n;i++){
s.insert(answer*2);
s.insert(answer*3);
s.insert(answer*5);
//类似队列操作
answer = *s.begin();
s.erase(answer);
}
return answer;
}
};
动态规划
递推公式——dp[i]=min(dp[p_2]*2,dp[p_3]*3,dp[p_5]*5)
动态规划是标识 3 个元素,通过比较他们的 2 倍、3 倍、5 倍的大小,来一个一个存
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> dp(n);
//初始化边界条件
dp[0]=1;
int p_2=0,p_3=0,p_5=0;//代表第几个数的2倍,3倍,5倍
for (int i=1;i<n;i++){
//小顶堆的方法是先存再排,dp 的方法则是先排再存
//每次计算三个丑数取最小,三个中必由两个参与上一次比较
dp[i]=min(min(2*dp[p_2],3*dp[p_3]),5*dp[p_5]);
//自增每次的最小丑数值的下标
if(dp[i]==2*dp[p_2]){
p_2++;
}
if(dp[i]==3*dp[p_3]){
p_3++;
}
if(dp[i]==5*dp[p_5]){
p_5++;
}
//通过三个if判断实现不重复
//假如一个数既可通过*2得到又可以通过*3得到,此时必然会重复计算并重复加入到数组
//所以if如果换成if-else,必然会有大量重复值出现
}
return dp[n-1];
}
};