题目要求:
我们把只包含因子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; }