LeetCode第 264 题:丑数II(C++)

tech2024-07-12  53

264. 丑数 II - 力扣(LeetCode)

前面一题:LeetCode第 263 题:丑数(C++)_zj-博客

一个丑数肯定是由另一个丑数乘以2, 3 或 5 而来的,因此有 “丑数 == 某较小丑数 × 某因子” (例如:10 = 5 x 2)

class Solution { public: int nthUglyNumber(int n) { unordered_set<long> s; priority_queue<long, vector<long>, greater<long>> q; q.push(1); s.insert(1); long val = 0; int a[] = {2,3,5}; for(int i = 0; i < n; ++i){ val = q.top(); q.pop(); for(int i = 0; i < 3; ++i){ long tmp = val * a[i]; if(!s.count(tmp)){ s.insert(tmp); q.push(tmp); } } } return val; } };

不用哈希表,手动去重:

class Solution { public: int nthUglyNumber(int n) { priority_queue<long, vector<long>, greater<long>> q; q.push(1); long val = 0; int a[] = {2,3,5}; for(int i = 0; i < n; ++i){ val = q.top(); q.pop(); for(int i = 0; i < 3; ++i) q.push(a[i]*val); while(val == q.top()) q.pop();//去重 } return val; } };

参考:暴力+优先队列(小顶堆)+动态规划(三指针) - 丑数 II - 力扣(LeetCode) dp:

class Solution { public: int nthUglyNumber(int n) { vector<int> dp(n, 0); dp[0] = 1; int p2 = 0, p3 = 0, p5 = 0; for(int i = 1; i < n; ++i){ dp[i] = min(dp[p2]*2, min(dp[p3]*3, dp[p5]*5)); //注意要使用3个if,因为可能会出现值相等的情况,此时两处的指针都要移动 if(dp[i] == dp[p2]*2) ++p2;//右移一位,表示这个因子已经考虑过了 if(dp[i] == dp[p3]*3) ++p3; if(dp[i] == dp[p5]*5) ++p5; } return dp[n-1]; } };

dp还是不太好理解的,注意每次加进去的都是最小的数,之间的优先级队列是先加进去然后自动排序,再依次取出最小的。而dp是先进行比较之后,在把最小的加进去。

这位大侠的理解挺有趣:三指针方法的理解方式 - 丑数 II - 力扣(LeetCode)

这位讲解的很清楚:丑数II, 合并 3 个有序数组, 清晰的推导思路 - 丑数 - 力扣(LeetCode)

最新回复(0)