设计一个算法,找出只含素因子2,3,5 的第 n 大的数。
符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12…
注意事项
我们可以认为1也是一个丑数
样例 如果n = 9, 返回 10
思路:
由题目的要求可知:找到出 2, 3, 5倍数的数。并排序。直到到第n个数
定义一个数组存放丑数,1是已知的丑数。
从2,3,5中挑选最小的添加到数组中
选择num[0]*2,num[0]*3,num[0]*5中最小的数为新的丑数,显然应该选择2,即num[1] = 2;
然后再从num[1]*2,num[0]*3,num[0]*5中进行选择,显然选择3,即num[2] = 3;
然后再从num[1]*2,num[1]*3,num[0]*5中选择最小的,选择2,即num[3] = 4,依次进行如下操作,
得到丑数后,在相应的丑数因子计数器上+1 以便于寻找下一个更大的丑数(数组中的丑数和因子构成新的丑数),
如果不更新,就不会产生新的丑数。
下一个丑数 = 之前生成的丑数数组中寻找一个 * (2 or 3 or 5)
在原有的数组中寻找新的丑数,因为2,3,5的(2,3,5)倍数也必然是丑数
public static int getMin(int num1, int num2, int num3){
//获得最小的值
int temp = num1 < num2 ? num1 : num2;
return temp < num3 ? temp : num3;
}
public int nthUglyNumber(int n) {
// write your code here
int[] ugly = new int[n];
ugly[0] = 1; //已知1为丑数
int num2 = 0; //定义因子计数器
int num3 = 0;
int num5 = 0;
for(int i = 1 ; i <n ; i++){
//新丑数是 2,3,5倍数中最小
ugly[i] = getMin(ugly[num2]* 2, ugly[num3] *3, ugly[num5] * 5);
//判断新存放的丑数是2,3,5哪个数的倍数
//并在相应的倍数对应计数器+1,使得与因子相乘的数值变化,得到新的丑数
if(ugly[i] == ugly[num2] * 2)
num2++;
if(ugly[i] == ugly[num3] * 3)
num3++;
if(ugly[i] == ugly[num5] * 5)
num5++;
}
return ugly[n-1];
}