有两个解决方法:
第一个,逐个判断每个整数是不是丑数的,对于每个数,判断该数是不是丑数,如果是丑数,那么计数加1,如果不是丑数那么判读下一个数,直到找到第1500个丑数。
丑数是指该数的最小因子只有2,3,5
那么判断一个数是不是丑数的方法就是,如果该数能被2整除,那么将该数除以2,能被3整除,则除以3,能被5整除,则除以5,看最后的数是不是1,如果是1那么该数就是丑数。
public int GetUglyNumber_Solution(int index) {
if(index<=0) return 0;
int number=0;
int times=0;
while(times<index){
++number;
if(isUgly(number)){
++times;
}
}
return number;
}
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;
}
但是这种方法时间复杂度太高,不能ac
第二种方法,用一个数组按照从小到大的顺序保存丑数。
如何依次序的保存丑数,如果当前丑数是M那么它的下一个丑数,肯定是前面所有的丑数中,乘以2恰好大于M的丑数M1,和乘以3恰好大于M的丑数M2,乘以5恰好大于M的丑数M3,中三者最小值min(M1,M2,M3)。
那么接下来如何得到这三个数M1,M2,M3?不用将M数前面的所有数都遍历一遍,分别定义数组中的三个索引,用来指向数组中的数使其该索引位置上的数,乘以2恰好大于M,乘以3恰好大于M,乘以5恰好大于M。
public int GetUglyNumber_Solution(int index) {
if(index<=0) return 0;
int[] numbers=new int[index];
int p1=0;//指向数组中最小乘以2大于下一个数的位置
int p2=0;
int p3=0;
numbers[0]=1;
int next=1;
while(next<index) {
numbers[next]=min(numbers[p1]*2,numbers[p2]*3,numbers[p3]*5);
while(numbers[p1]*2<=numbers[next]) {//找到下一个大于当前值的索引
p1++;
}
while(numbers[p2]*3<=numbers[next]) p2++;
while(numbers[p3]*5<=numbers[next]) p3++;
next++;
}
return numbers[index-1];
}
public int min(int o1,int o2,int o3) {
int min=o1<o2?o1:o2;
return min<o3?min:o3;
}