zoukankan      html  css  js  c++  java
  • 丑数

    题目

      把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数

    思路

    ,假设这个数为 n, 如果n是丑数,只有三种可能:

    1. n是能整除2,即 n % 2 == 0,且 n/2 是丑数。
    2. n % 3 == 0 且 n/3是丑数。
    3. n % 5 == 0且 n / 5是丑数。

    三种可能只要满足其中一种,就可以确认是丑数了。

    二 ,为了优化内存,只能想办法不存储所有的数了,而是用一个集合存储所有的丑数,如果要求第n个丑数,也就最多使用n个存储空间。而判断一个数是不是丑数的方法就是判断该数在不在这个集合中。

      可用unordered_set容器来存储“丑数”,先判断这个数是否在容器中,若是不在,并且该数是个“丑数”,就添加到容器中。

    三,如果已知了n个丑数,第n+1个丑数必然是前面的某个丑数乘以2,或者乘以3,或者乘以5。至于是谁,就是都尝试一下,取最小。

    现在已知6个丑数 1 2 3 4 5 6, 求第7个丑数。

    可以翻译成:假设dp[i]表示第i个丑数的数值,已知丑数的个数为count=6,且前6个丑数 dp[1]=1;dp[2]=2;dp[3]=3;dp[4]=4;dp[5]=5;dp[6]=6; 求dp[7]

    dp[7]可能有三种情况:

    • i=1开始按顺序求v = dp[i]*2,当v>dp[6],可以停止,则第4个丑数乘2得到的8可能是第7个丑数。
    • i=1开始按顺序求v = dp[i]*3,当v>dp[6],可以停止,则第3个丑数乘3得到的9可能是第7个丑数。
    • i=1开始按顺序求v = dp[i]*5,当v>dp[6],可以停止,则第3个丑数乘5得到的10可能是第7个丑数。

    取三种情况的最小值,得到8,就是第7个丑数,即dp[7] = 8

    依此类推,可以求得第8个丑数。

    有个小优化按顺序搜索的时候并不需要每次都从1开始,只需要从上次搜索的结束点继续搜索就行了

    例如求dp[8],同样有三种情况:

    • i=4开始按顺序求v = dp[i]*2,当v>dp[7],可以停止,则第5个丑数乘2得到的10可能是第8个丑数。
    • i=3开始按顺序求v = dp[i]*3,当v>dp[7],可以停止,则第3个丑数乘3得到的9可能是第8个丑数。
    • i=2开始按顺序求v = dp[i]*5,当v>dp[7],可以停止,则第2个丑数乘5得到的10可能是第8个丑数。

    取三种情况的最小值,得到10,即dp[8] = 9

    #include <iostream>
    #include <vector>
    #include <cmath>
    using namespace std;
    
    class Solution
    {
        public:
            int get_ugly_num(const int index);            
    };
    int Solution::get_ugly_num(const int index)
    {
        if(index<=0)
            return -1;
        else if(index<=6)
            return index;
        
        vector<int> v(index,0);
        for(int i=1;i<=6;++i)
            v[i]=i;
        
        int start1=1,start2=1,start3=1;
        int count=6;
        while(count<index)
        {
            for(int i=start1;i<=count;++i)
                if(v[i]*2>v[count])
                {
                    start1=i;
                    break;    
                }
                
            for(int i=start2;i<=count;++i)
                if(v[i]*3>v[count])
                {
                    start2=i;
                    break;
                }
                
            for(int i=start3;i<=count;++i)
                if(v[i]*5>v[count])
                {
                    start3=i;
                    break;
                }
            v[++count]=min(min(v[start1]*2,v[start2]*3),v[start3]*5);
        } 
        return v[count];
    }
    int main()
    {
        int n;
        cin>>n;
        Solution s;
        cout<<s.get_ugly_num(n)<<endl;
        return 0;
    }

     code2

    class Solution {
    public:
        int GetUglyNumber_Solution(int index) {
            if(index<7)
                return index;
            
            int t2=0,t3=0,t5=0;
            vector<int> res(index);
            res[0]=1;
            for(int i=1;i<index;++i)
            {
                res[i]=min(res[t2]*2,min(res[t3]*3,res[t5]*5));
                if(res[i]==res[t2]*2)
                    ++t2;
                if(res[i]==res[t3]*3)
                    ++t3;
                if(res[i]==res[t5]*5)
                    ++t5;
            }
            return res[index-1];
        }
    };
  • 相关阅读:
    C++中的extern "C"【转】
    无题
    MATLAB中文件的读写和数据的导入导出【转】
    逝去的2012
    C/C++语言中Static的作用详述
    C++:源文件与头文件有什么区别【转】
    Bash,后台与nohup
    关于include 和 extern
    python易错点
    android实现点击两次返回键实现退出功能
  • 原文地址:https://www.cnblogs.com/tianzeng/p/10259462.html
Copyright © 2011-2022 走看看