1. 题意
求第 k k k大的 2 i 3 j 5 k 2^{i}3^{j}5^{k} 2i3j5k
2. 题解
2.1 最小堆+哈希表
从最小的数开始,生成 2 i 3 i 5 i 2i\ 3i\ 5i 2i 3i 5i;判断这些数是否生成过,没生成过再将其插入堆中。
class Solution {
public:
int nthUglyNumber(int n) {
unordered_set<long long> seen;
seen.insert(1);
priority_queue<long long, vector<long long>, greater<long long> > p;
p.push(1);
long long ans = 0;
for (int i = 0;i < n; ++i) {
ans = p.top();
p.pop();
if (!seen.count(2 * ans)) {
p.push(2 * ans);
seen.insert(2 * ans);
}
if ( !seen.count(3 * ans) ) {
p.push(3 * ans);
seen.insert( 3 * ans);
}
if ( !seen.count( 5 * ans) ) {
p.push( 5 * ans );
seen.insert( 5 * ans );
}
}
return (int) ans;
}
};
2.2 动态规划
三个指针分别指向下一次的丑数需要生成 2 3 5 2\ 3\ 5 2 3 5倍的下一个丑数。
d p [ n ] = m i n { 2 d p [ p 2 ] , 3 d p [ p 3 ] , 5 d p [ p 5 ] } dp[n]=min\{2dp[p2],3dp[p3],5dp[p5]\} dp[n]=min{2dp[p2],3dp[p3],5dp[p5]}
class Solution {
public:
int nthUglyNumber(int n) {
std::vector<int> dp(1690,0);
dp[0] = 1;
int p2;
int p3;
int p5;
p2 = p3 = p5 = 0;
int v;
for (int i = 1;i < n;++i) {
v = min(dp[p2] *2, dp[p3] * 3);
v = min(dp[p5]*5,v);
dp[i] = v;
if ( v == dp[p2] * 2) {
p2++;
}
if ( v == dp[p3] * 3) {
p3++;
}
if ( v == dp[p5] * 5) {
p5++;
}
}
return dp[n - 1];
}
};