Loading

剑指 Offer 49. 丑数

思路

方法一:小顶堆

生成丑数的规律:如果已知丑数ugly,那么ugly * 2,ugly * 3和ugly * 5也都是丑数。
既然求第n小的丑数,可以采用最小堆来解决。每次弹出堆中最小的丑数,然后检查它分别乘以2、3和 5后的数是否生成过,如果是第一次生成,那么就放入堆中。第n个弹出的数即为第n小的丑数。

复杂度分析:

 1 class Solution {
 2 public:
 3     int nthUglyNumber(int n) {
 4         priority_queue<long long, vector<long long>, greater<long long>> minHeap;
 5         unordered_set<long long> seen;
 6         minHeap.push(1);
 7         seen.insert(1);
 8 
 9         int primes[3] = {2, 3, 5};
10         long long currentUgly, newUgly;
11         for(int i = 1; i <= n; ++i) {
12             currentUgly = minHeap.top();
13             minHeap.pop();
14 
15             for(int j = 0; j < 3; ++j) {
16                 newUgly = currentUgly * primes[j];
17                 if(!seen.count(newUgly)) {
18                     seen.insert(newUgly);
19                     minHeap.push(newUgly);
20                 }
21             }
22             
23         }
24 
25         return (int)currentUgly;
26     }
27 };

 

方法二:动态规划

复杂度分析:

时间复杂度: O(n) 
空间复杂度: O(n) 

 1 class Solution {
 2 public:
 3     int nthUglyNumber(int n) {
 4         int i2 = 0, i3 = 0, i5 = 0;
 5         vector<int> nums(n);
 6         nums[0] = 1;
 7         for(int i = 1; i < n; i++) {
 8             nums[i] = min(min(nums[i2] * 2, nums[i3] * 3), nums[i5] * 5);
 9             if(nums[i] == nums[i2] * 2) ++i2;
10             if(nums[i] == nums[i3] * 3) ++i3;
11             if(nums[i] == nums[i5] * 5) ++i5;
12         }
13         return nums[n - 1];
14     }
15 };

 

参考

力扣官方题解 - 丑数

 

posted @ 2020-11-09 13:07  拾月凄辰  阅读(65)  评论(0编辑  收藏  举报