题目要求:
我们把只包含因子2、3和5的数称为丑数。例如6、8都是丑数,但是14不是,因为它包含因子7.
习惯上我们把1当作是第一个丑数。
求按从小到大的顺序的第1500个丑数。
参考资料:剑指offer34题。
题目分析:
方法1 从1开始逐个遍历整数,每个整数如果包含2、3和5中的任何一个因子就除以该因子(包含多个就除以多个,直到不含2、3和5这三个因子),如果这样除得的结果为1,则表示只包含2、3和5,为丑数,此时丑数个数加1,直到个数为1500个。
缺点是:效率低,不管一个数是不是丑数都要作计算。
方法2 只计算丑数,后面的丑数根据前面的丑数和2、3、5来得出。计算过程如下图所示:
代码实现:
代码1:
#include <iostream>
using namespace std;
int GetUglyNumbers(int index);
int main(void)
{
//运行有点慢,需要等一下。可以用GetUglyNumbers(10)来测试。
cout << "第1500个丑数为:" << GetUglyNumbers(1500) << endl;
return 0;
}
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 GetUglyNumbers(int index)
{
if(index<=0)
return 0;
int number = 0;
int uglyFound = 0;
while(uglyFound < index)
{
number++;
if(IsUgly(number))
++uglyFound;
}
return number;
}
代码2:
#include <iostream>
using namespace std;
int GetUglyNumbers(int index);
int main(void)
{
//相比代码1,运行速度快了很多
cout << "第1500个丑数为:" << GetUglyNumbers(1500) << endl;
return 0;
}
int Min(int num1,int num2,int num3)
{
int min = (num1<num2)?num1:num2;
min = (min<num3)?min:num3;
return min;
}
int GetUglyNumbers(int index)
{
if(index<=0)
return 0;
int *pUglyNumbers = new int[index];
pUglyNumbers[0] = 1;
int nextUglyIndex = 1;
int *pUgly2 = pUglyNumbers;
int *pUgly3 = pUglyNumbers;
int *pUgly5 = pUglyNumbers;
while(nextUglyIndex < index)
{
int min = Min(*pUgly2*2,*pUgly3*3,*pUgly5*5);
pUglyNumbers[nextUglyIndex] = min;
while(*pUgly2*2 <= pUglyNumbers[nextUglyIndex])
++pUgly2;
while(*pUgly3*3 <= pUglyNumbers[nextUglyIndex])
++pUgly3;
while(*pUgly5*5 <= pUglyNumbers[nextUglyIndex])
++pUgly5;
++nextUglyIndex;
}
int ugly = pUglyNumbers[nextUglyIndex-1];
delete[] pUglyNumbers;
return ugly;
}