题目:
把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
解题思路:
参考程序员面试金典P190
每次将第n个丑数A存入列表时,利用其他三个列表Q2,Q3,Q5分别存储A*2,A*3,A*5.
找出三个列表中最小的元素,将它作为下一个丑数。
重复上述操作,直至找到第K个丑数。
优化在于:
当找出的丑数A位于Q2时,列表Q2,Q3,Q5分别存储A*2,A*3,A*5.
当找出的丑数A位于Q3时,只需列表Q3,Q5分别存储A*3,A*5.
(ps:因为A位于Q3,故能找到B满足A=3*B,若将A*2放入Q2,即2*3*B放入Q2,而2*3*B在Q3中已被处理过。这个过程可以简单的罗列下前几个元素,就可以看出)
当找出的丑数A位于Q5时,只需列表Q5存储A*5.
这个方法算优解了,稍微带点空间换时间的概率,但空间也在优化。不是无脑的上来直接把A*2,A*3,A*5全放到队列里,每次检索最小值,放到丑数队列中去。
在网上看到更牛逼的代码,没有辅助队列,只有三个辅助变量
直接上代码,简单到一点都不想解释
public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index<1){
return 0;
}
int[] array = new int[index];
int i2=0;
int i3=0;
int i5=0;
array[0]=1;
for(int i =0;i<index-1;i++){
int temp = getMin(array[i2]*2,array[i3]*3,array[i5]*5);
if(temp==array[i2]*2){
i2++;
}
if(temp==array[i3]*3){
i3++;
}
if(temp==array[i5]*5){
i5++;
}
array[i+1]=temp;
}
return array[index-1];
}
public int getMin(int a,int b,int c){
int min = a;
if(a>b){
min=b;
}
if(min>c){
min=c;
}
return min;
}
}