把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
看到这个题时,想到了早之前写过的如何判断一个数是否是质数,推广到如何判断一个数是不是丑数
因而根据质数的思路来写丑数
/**判断一个数是否为丑数
* @param n
* @return
*/
public boolean isUglyNumber(int n) {
boolean isUgly = true;
boolean isPrim = false;
for (int i = 2; i <= n; i++) {
if (n % i == 0) {
if (i % 2 == 0 || i % 3 == 0 || i % 5 == 0) {
isPrim = true;// 除了2,3,5外的非质数,包含2,3,5因子
} else if (i % 2 != 0 && i % 3 != 0 && i % 5 != 0) {
isUgly = false;// 包含了除2,3,5以外的因子以及除2,3,5以外的质数
break;
}
}
}
return isPrim && isUgly;
}
//然后根据计数输出第N个丑数
public int GetUglyNumber_Solution1(int index) {
if (index == 1) {
return 1;
}
int k = 1;
int n = 1;
while (k < index) {
n++;
if (isUglyNumber(n)) {
k++;
}
}
return n;
}
想法比较简单,然而无法通过牛客网的测试--算法复杂度过高,超时了!!!
想了很长时间没想出解决办法,参考了一下其他牛人的代码,发现思路错了,
本质原因是:丑数的形成是由丑数以及2,3,5构成的
思路是:将所有的丑数都存储在数组中,每次计算丑数的2,3,5倍,求出最小值,添加到数组中
根据这个思路,可以将程序简化为:
public int GetUglyNumber_Solution(int index) {
if(index==0){
return 0;
}
if (index == 1) {
return 1;
}
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
int k2 = 0,k3 = 0,k5 = 0;
while(list.size()<index){
int m2 = list.get(k2)*2;
int m3 = list.get(k3)*3;
int m5 = list.get(k5)*5;
int min = Math.min(m2, Math.min(m3, m5));
if(min==m2){
k2++;
}
if(min==m3){
k3++;
}
if(min==m5){
k5++;
}
list.add(min);
}
return list.get(list.size()-1);
}