把只包含因子2、3和5的数称作丑数,例如6是丑数,但14不是,因为它包含因子7,习惯上我们把1当作第一个丑数,求按从小到大的顺序的第N个丑数。
输入描述:整数N
输出描述:第N个丑数
第一种方法:遍历每一个整数i,若i能被2或者3或者5整除,count++,直到count = N时跳出循环,打印i
import java.util.Scanner;
public class KthUgly {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int count = 0;
int i;
for (i = 1; ; i++) {
if(isUgly(i))
count++;
if(count == n)
break;
}
System.out.println(i);
}
private static boolean isUgly(int n){
while(n%2 == 0)
n = n/2;
while(n%3 == 0)
n = n/3;
while(n%5 == 0)
n = n/5;
if(n == 1){
return true;
}
return false;
}
}
但是第一种方法效率不高,不仅要计算丑数,还要考虑非丑数。所以产生了改进的方法:只考虑丑数。下一个丑数是该丑数前面的丑数分别乘以2、3、5中最小的那个数。例如现有丑数序列为1下一个丑数要在12,13,15中选择最小且大于当前丑数的12,现在的丑数序列变成了1,2.下一个丑数要在13,15,22,23,25中选择最小其大于当前丑数的13,现在序列变成了1,2,3。下一个丑数要在15,22,23,25,32,33,35中选择最小且大于当前丑数的22…用一个数组顺序存储每一个丑数
import java.util.Scanner;
public class KthUgly {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println(getKthUgly(n));
}
private static int getKthUgly(int n){
if(n == 0)
return 0;
int[] ugly = new int[n];
int count = 1;
ugly[0] = 1;
int index2 = 0;
int index3 = 0;
int index5 = 0;
while(count < n){
int min = getMin(ugly[index2]*2, ugly[index3]*3, ugly[index5] *5);
ugly[count] = min;
while(ugly[index2] * 2 <= ugly[count]) index2++;
while(ugly[index3] * 3 <= ugly[count]) index3++;
while(ugly[index5] * 5 <= ugly[count]) index5++;
count++;
}
return ugly[n-1];
}
private static int getMin(int a, int b, int c){
return a>b?(b>c?c:b):(a>c?c:a);
}
}
但是对于此题我有一个很疑惑的点:
因子的定义是假如整数n除以m,结果是无余数的整数,那么我们称m就是n的因子。
丑数的定义是因子只包含2、3、5的数。
以此看来以上两个解法是不对的,因为按照代码可以得出8是丑数,但是根据因子的定义8的因子还包括4,所以8不是丑数。