丑数

一、题目

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

二、问题分析

假设这个数为 n, 如果n是丑数,只有三种可能:

n是能整除2,即 n % 2 == 0,且 n/2 是丑数。
n % 3 == 0 且 n/3是丑数。
n % 5 == 0且 n / 5是丑数。
三种可能只要满足其中一种,就可以确认是丑数了。即后面的丑数是由前一个丑数乘以2,3,5中的一个得来

状态转移方程

u(i) = min(u2(i-1)*2, u3(i-1)*3, u5(i-1)*5)  // u2、u3、u5代表2,3,5倍数的队列。

详细代码

/* 3个数中的最小值 */
int Min(int number1, int number2, int number3)
{
    int min = (number1 < number2) ? number1 : number2;
    min = (min < number3) ? min : number3;

    return min;
}

/* 创建数组保存已经找到的丑数,用空间换取时间 
 * 动态规划,对于第i个数,它一定是之前已存在数的2倍,3倍或5倍
 */
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;
}
作者:yusq77

-------------------------------------------

Wish you all the best and good health in 2021.

原文地址:https://www.cnblogs.com/yusq77/p/13546501.html