把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
解题思路
- 暴力枚举法(会超时,一般的C++程序运行10^9次就会超过1s而超时)
- 空间换时间,保存已计算的丑数,并通过已计算的丑数预测未来的丑数
上代码(C++香)
法一:暴力枚举法(超时)
#define maxN 10010
#define maxNN 0xFFFFFFF
// 判断是否是素数
bool isPrime(int num){
// 1不是素数
if(num < 2)
return false;
// 2是素数,不会执行for
for(int i = 2; i < num; i++){
if(!(num % i))
return false;
}
return true;
}
// 先求出一部分素数,数组下标为素数标记
void primeCache(int num[]){
for(int i = 0; i <= maxN; i++){
if(isPrime(i))
num[i] = 1;
}
}
// 先求出一部分素数,数组值为素数标记
void primeCachePlus(int num[]){
int m = 0;
for(int i = 2; i <= maxN; i++){
if(isPrime(i))
num[m++] = i;
}
}
bool isUglyNum(int prime[], int num){
if(num <= 1)
return true;
if(num % 2 != 0 && num % 3 != 0 && num % 5 != 0)
return false;
for(int i = 3; prime[i] <= num; i++){
// 不为0
if(!(num % prime[i]))
return false;
}
return true;
}
int GetUglyNumber_Solution(int index) {
// 得到素数缓存
int num[maxN];
memset(num, -1, sizeof(num));
primeCachePlus(num);
// 找到所有的丑数
int m = 0;
for(int i = 1; i <= maxNN; i++){
if(isUglyNum(num, i)){
m++;
if(m == index)
return i;
}
}
}
法二:暴力枚举法(超时,但这样的做法更妙)
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_SolutionPlus(int index) {
int number = 0;
int uglyFound = 0;
while(uglyFound < index){
number++;
if(isUgly(number))
uglyFound++;
}
return number;
}
法三:空间换时间,保存已计算的丑数,并通过已计算的丑数预测未来的丑数(AC)
int myMin(int number1, int number2,int number3){
int min = (number1 < number2) ? number1 : number2;
return (min < number3) ? min : number3;
}
int GetUglyNumber_Solution(int index) {
if(index <= 0)
return 0;
int pUglyNumbers[index];
memset(pUglyNumbers, -1, sizeof(pUglyNumbers));
pUglyNumbers[0]= 1;
int nextUglyIndex = 1;
int* pMultiply2 = pUglyNumbers;
int* pMultiply3 = pUglyNumbers;
int* pMultiply5 = pUglyNumbers;
while(nextUglyIndex < index){
// 求出当前最大的丑数
pUglyNumbers[nextUglyIndex] = myMin(*pMultiply2 * 2, *pMultiply3 * 3, * pMultiply5 * 5);
// 更新M2
while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex])
pMultiply2++;
while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex])
pMultiply3++;
while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex])
pMultiply5++;
nextUglyIndex++;
}
return pUglyNumbers[index - 1];
}