剑指Offer--034-丑数

链接


牛客OJ:丑数

九度OJ:http://ac.jobdu.com/problem.php?pid=1214

GitHub代码: 034-丑数

CSDN题解:剑指Offer–034-丑数

牛客OJ九度OJCSDN题解GitHub代码
034-丑数1214-丑数剑指Offer–034-丑数034-丑数


您也可以选择回到目录-剑指Offer–题集目录索引

题意


题目描述

把只包含因子2、3和5的数称作丑数(Ugly Number)。

例如6、8都是丑数,但14不是,因为它包含因子7。
习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

暴力方法


最简单直接的方法,就是逐个判断每个整数是不是丑数,循环所有数字,判断它是不是丑数
首先我们需要判断某个整数number是不是丑数

bool IsUglyNumber(int number)
{
    while(number % 5 == 0)
    {
        number /= 5;
    }

    while(number % 3 == 0)
    {
        number /= 3;
    }        

    while(number % 2 == 0)
    {
        number /= 2;
    }        

    return (number == 1);
}

然后接下来,就是按照顺序判断每一个整数是不是丑数

int GetUglyNumber_Solution(int index)
{
    if(index <= 0)
    {
        return -1;
    }

    int count = 1;
    int num = 0;

    while(count <= index)
    {
        num++;
        if(IsUglyNumber(num) == 1)
        {
            debug <<"count = "<<count <<", " <<num <<" is " <<endl;
            count++;
        }
    }

    return num;
}

寻找所有的丑数


根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。

因此我们可以创建一个数组,里面的数字是排好序的丑数。里面的每一个丑数是前面的丑数乘以2、3或者5得到的。那关键就是确保数组里的丑数是有序的了。

我们假设数组中已经有若干个丑数,排好序后存在数组中。我们把现有的最大丑数记做M。

现在我们来生成下一个丑数,该丑数肯定是前面某一个丑数乘以2、3或者5的结果。

我们首先考虑把已有的每个丑数乘以2。在乘以2的时候,能得到若干个结果小于或等于M的。由于我们是按照顺序生成的,小于或者等于M肯定已经在数组中了,我们不需再次考虑;

我们还会得到若干个大于M的结果,但我们只需要第一个大于M的结果,因为我们希望丑数是按从小到大顺序生成的,其他更大的结果我们以后再说。

我们把得到的第一个乘以2后大于M的结果,记为M2。同样我们把已有的每一个丑数乘以3和5,能得到第一个大于M的结果M3和M5。那么下一个丑数应该是M2、M3和M5三个数的最小者。

#include <iostream>

using namespace std;

//  调试开关
#define __tmain main

#ifdef __tmain

#define debug cout

#else

#define debug 0 && cout

#endif // __tmain

class Solution
{
protected:
    int ugly[10000];

    int min(int a, int b, int c)   
    {   
        int temp = (a < b ? a : b);   

        return (temp < c ? temp : c);   
    }

public:
    int GetUglyNumber_Solution(int N)
    {
        ugly[0] = 1;   
        int index2 = 0;   
        int index3 = 0;   
        int index5 = 0;   
        int index = 1;   
        while (index < N)   
        {   
            //竞争产生下一个丑数 
            int val = min(ugly[index2]*2, 
                          ugly[index3]*3, 
                          ugly[index5]*5);   

            if (val == ugly[index2] * 2) //将产生这个丑数的index*向后挪一位;  
            {
                ++index2;   
            }
            if (val == ugly[index3] * 3)   //这里不能用elseif,因为可能有两个最小值,这时都要挪动;
            {
                ++index3;   
            }
            if (val == ugly[index5] * 5)   
            {
                ++index5;   
            }

            ugly[index++] = val;   
        }
        int result = ugly[N - 1];   
        return result;  
    }
};

int __tmain( )
{
    Solution solu;
    cout <<solu.GetUglyNumber_Solution(3) <<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值