zoukankan      html  css  js  c++  java
  • 剑指 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];
        }
    };
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    第六天20160802
    第五天20160801
    关于表单元素input的美化
    关于Oracle默认用户名system密码不正确登录不上解决方案
    ORCALE安装教程
    [INS-32021]此卷上用于所选Oracle主目录的磁盘空间不足
    Linux下利用nc命令传输文件
    golang与 postgresql简单的增删改查
    Golang 调用 C/C++,例子式教程
    c# EF中equal的用法注意
  • 原文地址:https://www.cnblogs.com/itdef/p/14400239.html
Copyright © 2011-2022 走看看