题目:
我们把只包含因子2、3和5的数成为丑数,求按从小到大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做第一个丑数。
方法一:
分析:逐个判断整数是不是丑数,直观但是效率低下。
根据丑数的定义,丑数只能被2、3和5整除,也就是说一个数能被2整除,我们把它连续除以2;如果能被3整除,我们将它连续除以3;如果能被5整除,我们将它连续除以5;。如果自后得到1,那么这个数就是丑数。
代码如下:
#include<iostream>
#include<Windows.h>
using namespace std;
//判断一个数是否为丑数
bool isUgly(int num)
{
if (num <= 0)
return false;
while (num % 2 == 0)
num /= 2;
while (num % 3 == 0)
num /= 3;
while (num % 5 == 0)
num /= 5;
return (num == 1) ? true : false;
}
int GetUglyNum(int index)
{
if (index <= 0)
return 0;
int num = 0;//统计个数
int temp = 0;//从第1个数开始判断
while (num < index)
{
++temp;
if (isUgly(temp))
++num;
}
return temp;
}
int main()
{
DWORD start = GetTickCount();
cout << GetUglyNum(1500) << endl;
DWORD used = GetTickCount() - start;
cout << "耗时:" << used << "毫秒" << endl;
system("pause");
return 0;
}
运行结果:
859963392
耗时:38017毫秒
请按任意键继续. . .
注意:这种方法直观,代码简洁,但是最大的问题就是每一个整数都需要计算,因此效率低下。
方法二:
源代码如下:
#include<iostream>
#include<Windows.h>
using namespace std;
int Min(int num1, int num2, int num3)//返回三个数中最小值
{
return (num1 < num2) ? ((num1 < num3) ? num1 : num3) : ((num2 < num3) ? num2 : num3);
}
int GetUglySolution2(int index)
{
if (index <= 0)
return 0;
int *pUglyNumbers = new int[index];//申请内存空间,用来存储丑数
memset(pUglyNumbers, 0, index);//将内存中原始数据置为0
pUglyNumbers[0] = 1;//第一个丑数为1
int nextUglyIndex = 1;
int *M2 = pUglyNumbers;//*M2记录乘以2后的值,M2记录位置,初始时位置相同
int *M3 = pUglyNumbers;
int *M5 = pUglyNumbers;
while (nextUglyIndex < index)
{
int min = Min((*M2) * 2, (*M3) * 3, (*M5) * 5);
pUglyNumbers[nextUglyIndex] = min;//记录当前最大的丑数
//对位置进行重新定位
while (*M2 * 2 <= pUglyNumbers[nextUglyIndex])
++M2;//记录下第一次大于当前最大丑数的M2的位置
while (*M3 * 3 <= pUglyNumbers[nextUglyIndex])
++M3;
while (*M5 * 5 <= pUglyNumbers[nextUglyIndex])
++M5;
++nextUglyIndex;
}
int ugly = pUglyNumbers[nextUglyIndex - 1];
delete[] pUglyNumbers;
return ugly;
}
int main()
{
DWORD start = GetTickCount();
cout << GetUglySolution2(1500) << endl;
DWORD used = GetTickCount() - start;
cout << "耗时:" << used << "毫秒" << endl;
system("pause");
return 0;
}
运行结果:
859963392
耗时:0毫秒
请按任意键继续. . .
分析:
第二种方法效率明显提升,但是其消耗了1500*4*1024 = 6KB的存储空间。