题目:我们把只包含2、3和5的数称作丑数。求按从小到达的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7.习惯上把1当做第一个丑数。
方法1:如果一个数能被2整除,我们把它连续除以2;如果能被3整除,就连续除以3;如果能被5整除,就除以连续5.如果最后得到的是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;
}
int GetUglyNumber(int index){
if (index <= 0){
return 0;
}
int number = 0;
int uglyFound = 0;
while (uglyFound < index){
++number;
if (IsUgly(number)){
++uglyFound;
}
}
return number;
}
方法2:丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以2、3或者5得到的。关键在于怎样确保里面的丑数是排好序的。方法是,记录一个T2,T3和T5表示,排在它之前的每一个丑数乘以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;
}
int Min(int number1, int number2, int number3){
int min = (number1 < number2) ? number1 : number2;
min = (min < number3) ? min : number3;
return min;
}
测试用例:
- 功能测试(输入2、3、4、5、6等)
- 特殊输入测试(边界值1、无效输入0)
- 性能测试(输入较大的数字,如1500)