剑指Offer学习总结-丑数

剑指Offer学习总结-丑数

本系列为剑指Offer学习总结,主要是代码案例的分析和实现:
书籍链接:http://product.dangdang.com/24242724.html
原作者博客:http://zhedahht.blog.163.com/blog/static/254111742011101624433132/
原作者博客链接有完整的项目代码下载。


丑数

题目

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

遍历的解法:

我们逐个判断每个数字是否是丑数,所谓一个数 m 是另一个数 n 的因子是指 n 能被 m 整除也就是 n % m=0。
使用遍历法求第k个丑数,从1开始遍历,如果是丑数则count++,直到count=k为止。那么如何判断丑数呢?根据丑数的定义,丑数只有2,3,5这三个因子,那么我们就拿数字除以这三个因子。

bool IsUgly(int number)
{
    while(number % 2 == 0)
        number /= 2;
    while(number % 3 == 0)
        number /= 3;
    while(number % 5 == 0)
        number /= 5;
    return (number == 1) ? true : false;
}

int GetUglyNumber_Solution1(int index)
{
    if(index <= 0)
        return 0;

    int number = 0;
    int uglyFound = 0;
    while(uglyFound < index)
    {
        ++number;

        if(IsUgly(number))
        {
            ++uglyFound;
        }
    }
    return number;
}

该算法非常直观,代码也非常简洁,但最大的问题就在于每个整数都需要计算。即使一个数字不是丑数,我们还是需要对它做求余数和除法操作。因此该算法的时间效率不是很高

空间换时间的解法:

 根据丑数的定义,我们可以知道丑数可以由另外一个丑数乘以2,3或者5得到。因此我们可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以2,3或者5得到的。

我们把得到的第一个丑数乘以2以后得到的大于M的结果记为M2。同样,我们把已有的每一个丑数乘以3和5,能得到第一个大于M的结果M3和M5。

那么M后面的那一个丑数应该是M2,M3和M5当中的最小值:Min(M2,M3,M5)。
比如将丑数数组中的数字按从小到大乘以2,直到得到第一个大于M的数为止,那么应该是2*2=4

//这是原书的思路代码
int GetUglyNumber_Solution2(int index)
{
    if(index <= 0)
        return 0;

    int *pUglyNumbers = new int[index];
    pUglyNumbers[0] = 1;
    int nextUglyIndex = 1;

    int *pMultiply2 = pUglyNumbers;
    int *pMultiply3 = pUglyNumbers;
    int *pMultiply5 = pUglyNumbers;

    while(nextUglyIndex < index)
    {
        int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
        pUglyNumbers[nextUglyIndex] = min;

        while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex])
            ++pMultiply2;
        while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex])
            ++pMultiply3;
        while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex])
            ++pMultiply5;

        ++nextUglyIndex;
    }

    int ugly = pUglyNumbers[nextUglyIndex - 1];
    delete[] pUglyNumbers;
    return ugly;
}

//这是我的思路代码 感觉这种更容易理解和直观一点  
int GetUglyNumber_Solution21(int index)
{
    if (index <= 0)
        return 0;

    int *pUglyNumbers = new int[index];
    pUglyNumbers[0] = 1;
    int index_m = 0;

    int *pMultiply2 = pUglyNumbers;
    int *pMultiply3 = pUglyNumbers;
    int *pMultiply5 = pUglyNumbers;

    while (index_m < index-1)
    {
        while (*pMultiply2 * 2 <= pUglyNumbers[index_m])
            ++pMultiply2;
        while (*pMultiply3 * 3 <= pUglyNumbers[index_m])
            ++pMultiply3;
        while (*pMultiply5 * 5 <= pUglyNumbers[index_m])
            ++pMultiply5;

        int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
        pUglyNumbers[index_m+1] = min;

        ++index_m;
    }

    int ugly = pUglyNumbers[index_m];
    delete[] pUglyNumbers;
    return ugly;
}

你可能感兴趣的:(算法分析)