题目链接: leetcode.
这道题都做过一遍了喂(#`O′)竟然还是不会!
用堆,每次弹出堆顶的数, 将其分别乘以2,3,5压入堆
为了避免重复,使用哈希表存放已经生成的数
如果存int,在输入1690时溢出:
runtime error: signed integer overflow: 429981696 * 5 cannot be represented in type 'int'
/*
执行用时:160 ms, 在所有 C++ 提交中击败了9.06%的用户
内存消耗:33.5 MB, 在所有 C++ 提交中击败了5.04%的用户
*/
class Solution {
public:
int nthUglyNumber(int n) {
priority_queue<long, vector<long>, greater<long> > Q;
//priority_queue默认返回的是最大的 ,所以要加 greater<>
Q.push(1);
vector<int> ans;
unordered_set<long> S;
S.insert(1);
for(int i = 0;i < n;++i)
{
long t = Q.top();
ans.push_back(t);
Q.pop();
if(!S.count(t * 2))
{
S.insert(t * 2);
Q.push(t * 2);
}
if(!S.count(t * 3))
{
S.insert(t * 3);
Q.push(t * 3);
}
if(!S.count(t * 5))
{
S.insert(t * 5);
Q.push(t * 5);
}
}
return ans[n - 1];
}
};
使用动态规划的思想,用三个指针p2,p3,p5分别指向下一个应该乘的数
比较num[p2]*2
,num[p3]*3
和num[p5]*5
哪一个更小,便添加到数组后
将乘过的指针后移一位
(注意,每个与添加的数相等对应的指针都要移动,比如添加6,p2:3->4;p3:2->3)
/*
执行用时:8 ms, 在所有 C++ 提交中击败了83.57%的用户
内存消耗:7.4 MB, 在所有 C++ 提交中击败了79.94%的用户
*/
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> num(n);
num[0] = 1;
int p2 = 0, p3 = 0, p5 = 0;
int i = 1;
while(i < n)
{
int t = num[p2] * 2;
t = min(t, num[p3] * 3);
t = min(t, num[p5] * 5);
num[i] = t;
i++;
if(num[p2] * 2 == t)
p2++;
if(num[p3] * 3 == t)
p3++;
if(num[p5] * 5 == t)
p5++;
}
return num[n - 1];
}
};