剑指offer-面试题34:丑数

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

思路:(1)只包含因子2、3、5,那么用2、3、5除以后必定为1,可以作为丑数的判定标准。从1开始递增数字,每个数都判断是不是丑数,直到找到1500个。这种方法有很大的盲目性,每个数都不断的除以2、3、5效率非常低。

(2)不去判断一个数是不是丑数,而是找出下一个丑数。一个丑数它必定是前面的丑数乘上2或3或5得来的(为什么这样说?因为如果它不是前面的丑数乘上2或3或5,而是乘别的数得来的,那么说明他除了2、3、5还有别的因子,不符合丑数的定义),那么我们每次生成下一个丑数,直到生成1500个。那么被乘的前一个丑数如何确定?它应该满足乘上2或3或5之后刚好比当前已经生成的最大的丑数还要大,而且对2、3、5而言每一个数前面的丑数都是不一样的,每次生成一个丑数即需要更新乘数的位置。

这种算法只花费了额外的一点空间,遍历1500次,每次遍历移动了乘数的的几个指针,比思路1的方法要快得多。

实现代码:

int GetUglyNumber(int n)
{
    if(n < 0)
        return 0;
        
    int* UglyNumbers = new int[n];
    UglyNumbers[0] = 1;
    
    int* Multiply2 = UglyNumbers;
    int* Multiply3 = UglyNumbers;
    int* Multiply5 = UglyNumbers;
    
    int NextUglyIndex = 1;
    while(NextUglyIndex < n)
    {
        UglyNumbers[NextUglyIndex] = Min(*Multiply2 * 2, *Multiply3 * 3, *Multiply5 * 5);
        
        while(*Multiply2 * 2 <= UglyNumbers[NextUglyIndex])
            ++Multiply2;
        while(*Multiply3 * 3 <= UglyNumbers[NextUglyIndex])
            ++Multiply3;
        while(*Multiply5 * 5 <= UglyNumbers[NextUglyIndex])
            ++Multiply5;
            
        ++NextUglyIndex;
    }
    
    int ugly = UglyNumbers[NextUglyIndex - 1];
    delete[] UglyNumbers;
    return ugly;
}

int Min(int a, int b, int c)
{
    int tmp = a < b ? a : b;
    return tmp < c ? tmp : c;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值