题目:我们把只包含因子2,3,5的数称为丑数。求按从小达到的顺序的第1500个丑数。习惯上我们把1当作第一个丑数。
这个问题乍看不是很难,很容易想到快速的方法求解,可是效率总是很低!根据题目可以看出丑数是有规律的,都是2或3或5的倍数,除了1之外,那么我们就可以利用这一个规律求某个范围内的丑数,而不是每个数字都判断一下。
如何求一个丑数数组的下一个丑数,下一个丑数肯定比之前最后一个丑数要大,我们就可以用前面某一个丑数依次乘以那三个因子,肯定有大于或者小于当前这个最大的丑数的,我们选出最小的丑数(但又比当前这个丑数大的),作为下一个丑数就可以了。这种方法节省了时间,下面是代码:
// UglyNumber.cpp : Defines the entry point for the console application.
//
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 著作权所有者:何海涛
//#include "stdafx.h"
#include <stdio.h>
// ====================算法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_Solution1(int index)
{
if(index <= 0)
return 0;
int number = 0;
int uglyFound = 0;
while(uglyFound < index)
{
++number;
if(IsUgly(number))
{
++uglyFound;
}
}
return number;
}
// ====================算法2的代码====================
int Min(int number1, int number2, int number3);
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;
}
// ====================测试代码====================
void Test(int index, int expected)
{
if(GetUglyNumber_Solution1(index) == expected)
printf("solution1 passed\n");
else
printf("solution1 failed\n");
if(GetUglyNumber_Solution2(index) == expected)
printf("solution2 passed\n");
else
printf("solution2 failed\n");
}
int main()
{
Test(1, 1);
Test(2, 2);
Test(3, 3);
Test(4, 4);
Test(5, 5);
Test(6, 6);
Test(7, 8);
Test(8, 9);
Test(9, 10);
Test(10, 12);
Test(11, 15);
Test(1500, 859963392);
Test(0, 0);
return 0;
}