题目描述
设计一个算法,找出只含素因子2,3,5 的第 n 大的数。
符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12…
注意事项
我们可以认为1也是一个丑数
解法一
排除法
使用一个数组存储已知丑数, 分别用 2 ,3 ,5 整除自然数,在已知的丑数中查找是否存在。
优点:复杂度为 O(n)
缺点:太耗费 存储空间
public static int f(int n)
{
if (n == 1)
return 1;
HashMap<Integer, Boolean> result = new HashMap<>(n);
result.put(1, true);
int[] r = new int[n];
r[0] = 1;
int o = 2;
for (int i = 1; i < n; o++)
{
boolean sign = false;
if (o % 2 == 0)
{
if (result.get(o/2))
{
result.put(o, true);
r[i] = o;
i++;
sign = true;
}
} else if (o % 3 == 0)
{
if (result.get(o/3))
{
result.put(o, true);
r[i] = o;
i++;
sign = true;
}
} else if (o % 5 == 0)
{
if (result.get(o/5))
{
result.put(o, true);
r[i] = o;
i++;
sign = true;
}
}
if(sign == false){
result.put(o, false);
}
}
return r[n-1];
}
解法二
根据已有的丑数,直接乘以 2 , 3, 5 ,得到新的丑数
public static int f(int n)
{
if (n == 1)
return 1;
int[] r = new int[n];
r[0] = 1;
int n2 = 0,n3 = 0 ,n5 = 0;
int min;
for (int i = 1; i < n; i++)
{
min = Math.min(Math.min(2*r[n2], 3*r[n3]), 5*r[n5]);
r[i] = min;
//使 n2 ,n3 , n5 的值 为 小于 min 的最大值
for(; 2 * r[n2] <= min; n2++);
for(; 3 * r[n3] <= min; n3++);
for(; 5 * r[n5] <= min; n5++);
System.out.println(min + " " +n2+ " " + n3 + " " +n5);
}
System.out.println(Arrays.toString(r));
return r[n-1];
}