剑指 Offer 49. 丑数 && Leetcode 264. 丑数 II

地址 https://leetcode-cn.com/problems/chou-shu-lcof/

我们把只包含质因子 235 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

 

示例:

输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
说明:  

1 是丑数。
n 不超过1690。

解答1 

暴力遍历每个数 查看是不是丑数 显然是不行的

那么从1开始 每个丑数继续乘以2 乘以3 乘以5 就还是丑数,这样生成的丑数集合是没有遗漏的,排序后可以找到符合题目要求的丑数

不过2*3 和3*2 ,2*5 和5*2 会造成重复计算,时间上会超时。

我们考虑使用哈希避免重复计算。

使用最小堆保证每次放入答案集合中的是当前计算的最小丑数,这样使得答案是有序的,避免了排序。

两个小技巧就节省了不少时间,刚刚能够AC

class Solution {
public:
    unordered_set<int> ss;
    priority_queue<int, vector<int>, greater<int>> minHeap;
    vector<int> ans;
    int nthUglyNumber(int n) {
        minHeap.push(1);
        while(ss.size() < n&& !minHeap.empty()){
            int curr = minHeap.top();minHeap.pop();
            if(ss.count(curr) ==0){ 
                ss.insert(curr); ans.push_back(curr);
                if((long long) curr*2 < INT_MAX)
                    minHeap.push(curr*2);
                if((long long) curr*3 < INT_MAX)      
                    minHeap.push(curr*3); 
                if((long long) curr*5 < INT_MAX)
                    minHeap.push(curr*5); 
            }   
        }

        return ans[n-1];
    }
};

 

解答2 

我们已经明确了 一个非1的丑数 如果能够除以2 3 或者5 就能得到一个比它小的丑数,比如 6可以除以3 得到2,6除以2得到3. 30可以得到 2 3 5 6 15 10等丑数

所有的丑数 都可以从比他大的某个丑数通过这种方式计算得到,也就达到了不重不漏中的不漏。

我们剩下的问题就是避免不重复而有序的生成这些丑数

这里设置三个队列 专门有序存放当前答案集合中存放的丑数的2 3 5的倍数

每次从三个队列中取出最小的数放入答案集合,并且将这个数乘以2 3 5放入相应的队列

那么答案集合中的丑数是有序的,三个队列中的丑数也是有序的

如图

-----------------------------------------------------------------------

 

class Solution {
public:
    queue<long long> a;
    queue<long long> b;
    queue<long long> c;
    vector<int> ans;
    int nthUglyNumber(int n) {
        ans.push_back(1); a.push(2); b.push(3); c.push(5);
        while (ans.size() < n) {
            int curr = min(a.front(), min(b.front(), c.front()));
            ans.push_back(curr);
            if (curr == a.front()) a.pop();
            if (curr == b.front()) b.pop();
            if (curr == c.front()) c.pop();
            a.push((long long )curr * 2); b.push((long long )curr * 3); c.push((long long )curr * 5);
        }

        return ans[n - 1];
    }
};

 

posted on 2021-02-13 15:39  itdef  阅读(111)  评论(0编辑  收藏  举报

导航