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