题目:
我们称只包含因子2,3,5的数为丑数,比如9,但是14不是,因为包含因子7。我们要求找到前1500个丑数。
分析:
直观的方法就是穷举1,2,3...n,每次得到一个数,我们穷举它的因子2,3,5,穷除这些因子后,数最后只剩1,表示这个数是丑数,但是这种方法显然不好,计算量大。
另一种方法,类似于筛选素数的方法,我们将已经得到丑数,乘上2,3,5,那么新生成的数也一定是丑数,关键问题就是如何按顺序依次生成丑数,我们采用三个指针,代表乘以2,3,5相乘的数的位置,每次选取这三个指针得到的丑数最小值,这样我们能保证结果是有序的。
代码如下:
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
int min(int a, int b)
{
return a < b ? a : b;
}
int main()
{
int index = 10;
int *pNumber = new int[index + 1];
pNumber[0] = 1; //应用一点小技巧,程序更简洁
int nextUgly = 1;
int *pugly2 = pNumber;
int *pugly3 = pNumber;
int *pugly5 = pNumber;
while (nextUgly <= index)
{
int min_number = min(min((*pugly2) * 2, (*pugly3) * 3), (*pugly5) * 5);
pNumber[nextUgly] = min_number;
while ((*pugly2) * 2 <= pNumber[nextUgly]) //找到最小的2倍丑数
pugly2++;
while ((*pugly3) * 3 <= pNumber[nextUgly]) //找到最小的3倍丑数
pugly3++;
while ((*pugly5) * 5 <= pNumber[nextUgly]) //找到最小的5倍丑数
pugly5++;
nextUgly++;
}
for(int i = 1; i <= index; i++)
cout << pNumber[i] << " ";
return 0;
}
总结:
学会用筛选法,用空间换取时间,素数筛选过程中,也应用到了类似的思想。