剑指offer-丑数

/*******************************************************************
Copyright(c) 2016, Tyrone Li
All rights reserved.
*******************************************************************/
// 作者:TyroneLi
//

/*
Q:
    丑数:
        把只包含因子2,3,5的数称为丑数,求按照从小到大的顺序的第1500个丑数。
        习惯上我们把1当作是第一个丑数。
S:
    1. 按照从1到第1500个丑数的顺序,逐个判断每个整数能不能只包含因子2,3,5;
       一个整数如果包含因子2,那么可以被2连续整除;同理3,,5;最后被这三个
       整肃连续整除的结果就是只剩下1。这种方法需要把非丑数的整肃也考虑进来,
       时间效率不是很高。
    2. 使用空间换时间的做法,一个丑数肯定是前面某个丑数的2,3,5倍,因此可以使用
       这样的策略来求得后面一个丑数,假设已经有前面部分排序的丑数,那么可以有前面
       某个丑数的2,3,5倍的数大于前面部分排序丑数最大的那个数的最小那个。因此我们
       可以根据前面已经保存的丑数计算后面的丑数。
*/

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>

bool isUgly(int num)
{
    while(num % 2 == 0)
        num /= 2;
    while(num % 3 == 0)
        num /= 3;
    while(num % 5 == 0)
        num /= 5;
    bool result = (num == 1)?true:false;
    // std::cout << result << std::endl;
    return result;
}

int uglyNum_slow(int uglyIndex)
{
    if(uglyIndex <= 0)
        return 0;
    
    int num_idx =0;
    int ugly_idx = 0;
    while(ugly_idx < uglyIndex)
    {
        // std::cout << ugly_idx << std::endl;
        // std::cout << num_idx << std::endl;
        ++num_idx;
        if(isUgly(num_idx))
            ++ugly_idx;
    }
    return num_idx;
}

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

int uglyNum(int uglyIndex)
{
    if(uglyIndex <= 0)
        return 0;
    
    int*uglyNumsSeq = new int[uglyIndex];
    int*ugly_2 = uglyNumsSeq;
    int*ugly_3 = uglyNumsSeq;
    int*ugly_5 = uglyNumsSeq;
    uglyNumsSeq[0] = 1;
    int uglyIdx = 1;
    while(uglyIdx < uglyIndex)
    {
        int min_tmp = min(*ugly_2*2, *ugly_3*3, *ugly_5*5);
        uglyNumsSeq[uglyIdx] = min_tmp;
        while((*ugly_2)*2 <= uglyNumsSeq[uglyIdx]) ugly_2++;
        while((*ugly_3)*3 <= uglyNumsSeq[uglyIdx]) ugly_3++;
        while((*ugly_5)*5 <= uglyNumsSeq[uglyIdx]) ugly_5++;

        ++uglyIdx;
    }
    int ugly_rst = uglyNumsSeq[uglyIdx - 1];
    delete[] uglyNumsSeq;
    return ugly_rst;
}

void test_1()
{
    std::cout << "Test 1" << std::endl;
    for(int i = 0; i < 101; ++i)
        std::cout << "1500th ugly number " << uglyNum(i) << std::endl;
    
    for(int i = 0; i < 101; ++i)
        std::cout << "1500th ugly number " << uglyNum_slow(i) << std::endl;
}

void test_2()
{
    std::cout << "Test 2" << std::endl;
    std::cout << "0 ugly number " << uglyNum(0) << std::endl;
    std::cout << "1 ugly number " << uglyNum(1) << std::endl;
    std::cout << "2 ugly number " << uglyNum(2) << std::endl;
    std::cout << "3 ugly number " << uglyNum(3) << std::endl;
    std::cout << "4 ugly number " << uglyNum(4) << std::endl;
    std::cout << "5 ugly number " << uglyNum(5) << std::endl;
    std::cout << "6 ugly number " << uglyNum(6) << std::endl;
    
    std::cout << "0 ugly number " << uglyNum_slow(0) << std::endl;
    std::cout << "1 ugly number " << uglyNum_slow(1) << std::endl;
    std::cout << "2 ugly number " << uglyNum_slow(2) << std::endl;
    std::cout << "3 ugly number " << uglyNum_slow(3) << std::endl;
    std::cout << "4 ugly number " << uglyNum_slow(4) << std::endl;
    std::cout << "5 ugly number " << uglyNum_slow(5) << std::endl;
    std::cout << "6 ugly number " << uglyNum_slow(6) << std::endl;
    
}

void test_uglyNum()
{
    test_1();
    test_2();
}
int main(int argc, char**argv)
{

    test_uglyNum();

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值