给你一个整数 n ,请你找出并返回第 n 个 丑数 。
**说明:**丑数是只包含质因数 2、3 或 5 的正整数;1 是丑数。
示例 1:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
提示:
1 <= n <= 1690
首先可以知道,后面的丑数都是由前面的丑数乘以2或3或5得到的,但是我们不知道先出现的是哪个数乘以哪个值
可以考虑维护一个最小堆,同时使用哈希表避免重复,这样相当于我们是先求值再排序,直到能确定位置的丑数的个数达到n个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Solution { public: int nthUglyNumber(int n) { priority_queue<long, vector<long>, greater<long>> q; q.push(1); unordered_map<long, bool> hash; hash[1] = true; vector<long> flag = {2, 3, 5}; long mid; while (n) { mid = q.top(); for (int i = 0; i < 3; i++) { long midmid = mid * flag[i]; if (!hash[midmid]) { q.push(midmid); hash[midmid] = true; } } q.pop(); n--; } return mid; } };
|
也可以使用三个指针,分别表示应该由2或3或5乘以当前位置的丑数;
每次求一个丑数就是
1
| dp\lbrack i\rbrack = min(2 \ast dp\lbrack p2\rbrack,3 \ast dp\lbrack p3\rbrack,5 \ast dp\lbrack p5\rbrack)
|
再把对应指针加一,再继续比较求下一个丑数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: int nthUglyNumber(int n) { vector<long> dp(n + 1); dp[0] = 1; int p2 = 0, p3 = 0, p5 = 0; for (int i = 1; i <= n; i++) { long d2 = dp[p2] * 2; long d3 = dp[p3] * 3; long d5 = dp[p5] * 5; dp[i] = min(d2, min(d3, d5)); if (dp[i] == d2) p2++; if (dp[i] == d3) p3++; if (dp[i] == d5) p5++; } return dp[n - 1]; } };
|