【编程题目】寻找丑数

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

 

思路:

1.  数字从1递增,判断是不是丑数

2. 用2、3、5分别乘以已有的丑数,用大于当前的丑数的结果中最小的作为当前的丑数 快!

/* 
64.  寻找丑数(运算)。
题目:我们把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 6、8 都是丑数,
但 14 不是,因为它包含因子 7。习惯上我们把 1 当做是第一个丑数。
求按从小到大的顺序的第 1500 个丑数。
*/
#include <stdio.h>
#include <stdlib.h>

int uglynum(int n) //输入要找第几个丑数
{
    long int i;
    int num = 1;
    for (i = 2; num < n; i++)
    {
        int flag = 0;
        int d = i;
        while (d != 1 && 0 == flag)
        {
            if (d % 2 == 0)
            {
                d = d/2;
            }
            else if (d % 3 == 0)
            {
                d = d/3;
            }
            else if (d % 5 == 0)
            {
                d = d/5;
            }
            else
            {
                flag = 1;
            }
        }
        if (0 == flag)
        {
            num++;
        }
    }
    return (i - 1);
}

int uglynum2(int n) //输入要找第几个丑数
{
    if (n == 1)
    {
        return 1;
    }
    int* data = (int *)malloc(n * sizeof(n));
    data[0] = 1;
    int b[3] = {2, 3, 5};
    for (int i = 1; i < n; i++)
    {
        int mintmp = 2 * data[i - 1]; //存储比上一个数字大的数中最小的那个 初始化这个数
        for(int m = 0; m < 3; m++)
        {    
            for (int j = 0; j < i; j++)
            {
                if (data[j] * b[m] > data[i - 1])
                {
                    if (data[j] * b[m] < mintmp)
                    {
                        mintmp = data[j] * b[m];
                    }
                    break;
                }
            }
        }
        data[i] = mintmp;
    }

    int ans = data[n - 1];
    free(data);
    return ans;
}
int main()
{
    //long int d = uglynum(1500);
    //d = uglynum2(1500);
    for (int i = 2; i <= 1500; i++)
    {
        int d = uglynum2(i);
        printf("第%d个丑数为:%d\n", i, d);
    }
    return 0;
}

 

网上看答案,发现自己写的不好,虽然思路一样,但是我写的看起来很乱。而且在方法二中我对 2 3 5都是从第一个数字开始乘,实际上可以用三个指针记录上一次乘到哪里了,下一次从记录位开始找就好了。

还有,有些子功能可以写成子函数,可以让整个代码看起来更清晰。

http://www.cnblogs.com/mingzi/archive/2009/08/04/1538491.html 里的代码就看起来很舒服。

方法一:

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;
}

方法二:

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 Min(int number1, int number2, int number3)
{
    int min = (number1 < number2) ? number1 : number2;
    min = (min < number3) ? min : number3;

    return min;
}

 

posted @ 2014-08-15 14:27  匡子语  阅读(903)  评论(0编辑  收藏  举报