Write a program to find the n
-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5
.
Example:
Input: n = 10 Output: 12 Explanation:1, 2, 3, 4, 5, 6, 8, 9, 10, 12
is the sequence of the first10
ugly numbers.
Note:
1
is typically treated as an ugly number.n
does not exceed 1690.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
这道题搞了俩小时,终于大概理解了
-------------------------------------------------------
第一种思路:
线性扫描1,2,3,4,5,6,7,8,9,10,11,12,13,14......
逐个进行判断,如果是ugly number的话就增加ugly number的count
直到count满足要求,返回即可
但是这种方法是线性时间的,而且判断是不是ugly number的计算量较大,LeetCode超时了
// 超时方案
// public int nthUglyNumber(int n) {
// int number = 1;
// int count = 1;
// while(count<n){
// number++;
// if(isUgly(number)){
// count++;
// }
// }
// return number;
// }
// private boolean isUgly(int number){
// //丑数一定等于 (2**x)*(3**y)*(5**z)
// number = max_divide(number,2);
// number = max_divide(number,3);
// number = max_divide(number,5);
// return number==1;
// }
// private int max_divide(int number,int k){
// while(number%k==0){//number能整除k
// number /= k;
// }
// return number;
// }
-------------------------------------------------------------------------
第二种思路:
假如我们已知丑数序列(当然,我们并不知道,就是假如)如下:
1, 2, 3, 4, 5, 6, 8, 9, 10, 12
那么对上面这个丑数序列分别乘以2,3,5 将得到三个新的序列,这三个序列仍然是丑数序列。因为这三个序列中的数相对于原来的丑数序列,只多了数本身和2/3/5这两个因子。
1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 8*2, 9*2, 10*2, 12*2
1*3, 2*3, 3*3, 4*3, 5*3, 6*3, 8*3, 9*3, 10*3, 12*3
1*5, 2*5, 3*5, 4*5, 5*5, 6*5, 8*5, 9*5, 10*5, 12*5
第一个丑数是1, 然后对上面这三个有序序列进行合并。
注意两点:
第一: 三个丑数序列中有重复的数,要注意去重。
第二:我们不可能事先知道丑数序列,是在计算丑数序列的过程中,用之前算出来的丑数作为已知的丑数序列
由于事先不知道丑数序列,三个数组在合并时的位置索引是通过uglys来记录的,
toMergeInSeq? = uglys[idx4seq?]*? (?=2,3,5)
uglys: 丑数数组
toMergeInSeq? : 序列?接下来要归并的候选人(?=2,3,5)
idx4seq? : toMergeInSeq? = uglys[idx4seq?]*? (?=2,3,5)
class Solution {
public int nthUglyNumber(int n) {
int[] uglys = new int[n];
uglys[0] = 1;
int toMergeInSeq2= 2,toMergeInSeq3 = 3,toMergeInSeq5 = 5;
int idx4seq2 = 0, idx4seq3=0 ,idx4seq5 = 0;//toMergeInSeq? = uglys[idx4seq?]*? (?=2,3,5)
for(int i = 1;i<n;i++){
int ugly = Math.min( Math.min(toMergeInSeq2,toMergeInSeq3),toMergeInSeq5 );
uglys[i] = ugly;
//由于三个序列有重复值,在合并的时候需要排除重复。三个if可能执行多个,并不是一定只执行一个if
if(ugly==toMergeInSeq2){
idx4seq2++;
toMergeInSeq2 = uglys[idx4seq2]*2;
}
if(ugly==toMergeInSeq3){
idx4seq3++;
toMergeInSeq3 = uglys[idx4seq3]*3;
}
if(ugly==toMergeInSeq5){
idx4seq5++;
toMergeInSeq5 = uglys[idx4seq5]*5;
}
}
return uglys[n-1];
}
}