面试题34:丑数
标签: 剑指offer
题目描述:
只包含因子2,3,5的数称为丑数,1是第一个丑数,求第n个丑数是什么。
思路:
1 . 暴力法。
从1开始遍历每个整数,判断每个数是不是丑数,是的话计数器加1,当计数器等于n时,返回当前遍历到的整数。这种算法要计算1到第n个丑数中间的所有数。
// 判断一个数是否为丑数
public boolean 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;
}
// 计算第n个丑数
public int getNthUglyNumber(int n){
if(n <= 0) return 0;
int number = 0;
int count = 0;
while(count < n){
number++;
if(isUgly(number)) count++;
}
return number;
}
2 . 空间换时间法
使用数组存储1开始的所有丑数,每次根据已有丑数计算下一个丑数,并加到数组中,直到n个丑数全部算出来。
这种算法只需要计算每一个丑数,忽略掉不是丑数的数,比第一种思路好,但是需要n的空间。
丑数生成规则,由已有丑数x2,x3,x5中选取一个最小值作为下一个丑数。这里t2,t3,t5是能生成最新丑数的已有丑数下标,需要不断更新。
public int getNthUglyNumber(int n){
if(n <= 0) return 0;
int [] uglys = new int[n];
uglys[0] = 1;
int pCurr = 0;
int t2 = 0; t3 = 0; t5 = 0;
while(pCurr < n){
int curr = min(uglys[t2] * 2, uglys[t3] * 3, uglys[t5] * 5);
uglys[pCurr] = curr;
while(uglys[t2] * 2 <= curr) t2++;
while(uglys[t3] * 3 <= curr) t3++;
while(uglys[t5] * 5 <= curr) t5++;
pCurr++;
}
int result = uglys[n - 1];
return result;
}