【编程题目】寻找丑数

题目:我们把只包含因子 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;

}

 

你可能感兴趣的:(编程)