给你一个整数 n ,请你找出并返回第 n 个 丑数 。
丑数 就是只包含质因数 2、3 和/或 5 的正整数。
示例 1:
输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。
示例 2:
输入:n = 1
输出:1
解释:1 通常被视为丑数。
提示:
1 <= n <= 1690
思路:
我开头的思路是用递归,然后已经算过的值就不再算,效率实在太差了,
超过300多位速度就会非常慢,导致超时。
正确的思路是使用堆的方式,(优先队列),每次取最小的丑数:min
新的丑数为:
min * 2;
min * 3
min * 5
其中考虑,如 2*6 = 12 , 3*4 = 12
存在值会重复的情况,需要使用哈希进行去重即可。
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
using namespace std;
class Solution {
public:
int nthUglyNumber(int n) {
priority_queue <long, vector<long>, greater<long>> q;
unordered_set<long> u;
vector<long> mask = { 2,3,5 };
//vector<int> ugNum;
double qTop = 1;
q.push(qTop);
for (int i = 0; i < n; i++) {
for (int j = 0; j < mask.size(); j++) {
if (u.count(mask[j] * qTop) == 0) {
u.insert(mask[j] * qTop);
q.push(mask[j] * qTop);
}
}
//ugNum.push_back(qTop);
qTop = q.top();
q.pop();
}
//for (int i = 0; i < ugNum.size(); i++) {
// cout << ugNum[i] << endl;
//}
return qTop;
}
};
int main() {
Solution* ps = new Solution();
cout << ps->nthUglyNumber(10) << endl;
system("pause");
return 0;
}
记忆化搜索代码,超时:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> arr;
unordered_map<int,bool> ugMap;
ugMap[1] = true;
ugMap[2] = true;
ugMap[3] = true;
int i = 1;
while (arr.size() < n) {
if (judgeIsUgNum(i, ugMap)) {
ugMap[i] = true;
arr.push_back(i);
}
i++;
}
return arr[n - 1];
}
private:
bool judgeIsUgNum(int val, unordered_map<int,bool>& ugMap) {
if (ugMap[val] == true) {
return true;
}
if (val % 2 == 0) {
return judgeIsUgNum(val / 2, ugMap);
}
else if (val % 3 == 0) {
return judgeIsUgNum(val / 3, ugMap);
}
else if (val % 5 == 0) {
return judgeIsUgNum(val / 5, ugMap);
}
else {
return false;
}
}
};