前面一题:LeetCode第 263 题:丑数(C++)_zj-CSDN博客
一个丑数肯定是由另一个丑数乘以2, 3 或 5 而来的,因此有 “丑数 == 某较小丑数 × 某因子” (例如:10 = 5 x 2)
class Solution {
public:
int nthUglyNumber(int n) {
unordered_set<long> s;
priority_queue<long, vector<long>, greater<long>> q;
q.push(1);
s.insert(1);
long val = 0;
int a[] = {2,3,5};
for(int i = 0; i < n; ++i){
val = q.top();
q.pop();
for(int i = 0; i < 3; ++i){
long tmp = val * a[i];
if(!s.count(tmp)){
s.insert(tmp);
q.push(tmp);
}
}
}
return val;
}
};
不用哈希表,手动去重:
class Solution {
public:
int nthUglyNumber(int n) {
priority_queue<long, vector<long>, greater<long>> q;
q.push(1);
long val = 0;
int a[] = {2,3,5};
for(int i = 0; i < n; ++i){
val = q.top();
q.pop();
for(int i = 0; i < 3; ++i) q.push(a[i]*val);
while(val == q.top())
q.pop();//去重
}
return val;
}
};
参考:暴力+优先队列(小顶堆)+动态规划(三指针) - 丑数 II - 力扣(LeetCode)
dp:
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> dp(n, 0);
dp[0] = 1;
int p2 = 0, p3 = 0, p5 = 0;
for(int i = 1; i < n; ++i){
dp[i] = min(dp[p2]*2, min(dp[p3]*3, dp[p5]*5));
//注意要使用3个if,因为可能会出现值相等的情况,此时两处的指针都要移动
if(dp[i] == dp[p2]*2) ++p2;//右移一位,表示这个因子已经考虑过了
if(dp[i] == dp[p3]*3) ++p3;
if(dp[i] == dp[p5]*5) ++p5;
}
return dp[n-1];
}
};
dp还是不太好理解的,注意每次加进去的都是最小的数,之间的优先级队列是先加进去然后自动排序,再依次取出最小的。而dp是先进行比较之后,在把最小的加进去。
这位大侠的理解挺有趣:三指针方法的理解方式 - 丑数 II - 力扣(LeetCode)