题目
我们把只包含因子2、3和5的数称作丑数(Ugly Number)。 求按从小到大的顺序的第1500个丑数。1是一个特殊的丑数。
我们可以通过下面的函数来判断一个数是不是丑数:
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;
}
思路
原则:丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。通过第一个丑数去推导后面所有排序好的丑数。
(1)定义一个长度为Index的数组,Index为你需要排序好的丑数的下标。数组的第一个元素为1,每个元素都是排序好的丑数。
(2)定义下标T2、T3和T5。T2表示当前数组中,将T2下标中存放的丑数乘以2会超过当前数组中已有的最大丑数M;同理,T3表示将此下标的丑数乘以3会超过当前数组中已有的最大丑数M;T5表示将此下标的丑数乘以5会超过当前数组中已有的最大丑数M;
(3)找寻下一个丑数:T2 * 2、 T3 * 3、 T5 * 5中的最小值
(4)将丑数填入数组,并更新T2、T3、T5。
代码
#include <iostream>
using namespace std;
// 返回三个数中的最小值
int Min(int number1, int number2, int number3)
{
int min = std::min(number1,number2);
min = std::min(number3,min);
return min;
}
// 获取第index个丑数
int GetUglyNumber_Solution(int index)
{
if (index <= 0)
return 0;
int *pUglyNumbers = new int[index];
pUglyNumbers[0] =1; // 1是第1个丑数
int nextUglyIndex = 1; // 下一个丑数的下标
int *pMultiply2 = pUglyNumbers; // T2
int *pMultiply3 = pUglyNumbers; // T3
int *pMultiply5 = pUglyNumbers; // T5
while (nextUglyIndex < index)
{
int min = Min(*pMultiply2*2, *pMultiply3*3, *pMultiply5*5);
pUglyNumbers[nextUglyIndex] = min;
while (*pMultiply2*2 <= pUglyNumbers[nextUglyIndex]) // 更新T2
++pMultiply2;
while (*pMultiply3*3 <= pUglyNumbers[nextUglyIndex]) // 更新T3
++pMultiply3;
while (*pMultiply5*5 <= pUglyNumbers[nextUglyIndex]) // 更新T5
++pMultiply5;
++nextUglyIndex;
}
int ugly = pUglyNumbers[nextUglyIndex - 1];
delete[](pUglyNumbers);
return ugly;
}
int main()
{
int index = 1500;
printf("The %dth Ugly Number is %d\n", index, GetUglyNumber_Solution(index));
return 0;
}