用空间换时间
一、逐个判断是否是丑数,直观但不高效
二、根据丑数的定义,丑数应该是另一个丑数乘以2,乘以3或者乘以5(1除外)
解决方案:
创建一个数组,里面的数组都是排好序的,每一个丑数都是前面的丑数乘以2,乘以3或者乘以5得到的
重点:怎样确保数组中的丑数都是排好序的????
首先:把已有的丑数乘以2(其中最小值为M2)得到的大于已有数组中最大的丑数,乘以3(其中最小值为M3)得到的大于已有数组中最大的丑数,乘以5(其中最小值为M5),M2,M3,M5最小值为下一个丑数
其次:不用所有丑数都乘以2,3,5;找到一个值T2,T2前面的丑数乘以2都小于等于数组的最大丑数。用一个标记来标记该丑数的位置。
每次生成新的丑数时,要去更新标记位置T2的值
代码:
package core;
/**
* 问题描述:将只含有因子2,3,5的称为丑数,求按从小到大的顺序的第1500个丑数
* 例如:6,8都是丑数,而14不是
* 习惯上我们把1当成第1个丑数
* Created by lxq on 2017/9/7.
*/
public class Problem {
public static void main(String[] args){
Problem problem = new Problem();
System.out.println(problem.getUglyNumber(1500));
}
public int getUglyNumber(int n){
if(n<0)
return 0;
int[] uglyArray = new int[n];
uglyArray[0] = 1;
//标记,在t2之前的丑数*2都小于已有的最大的丑数
int t2 = 0; //默认第一个丑数标记位置为0
int t3 = 0;
int t5 = 0;
for(int i=1;i<n;i++){
//已有的丑数乘以2,3,5是较小的是下一个丑数
int min = min(uglyArray[t2]*2,uglyArray[t3]*3,uglyArray[t5]*5); //得到下一丑数
uglyArray[i] = min;
//更新标记丑数 t2,t3,t5的位置,只需比较 标记*2|*3|*5的中较小的一个就可以了
while(uglyArray[t2]*2<=min)
t2++;
while (uglyArray[t3]*3<=min)
t3++;
while(uglyArray[t5]*5<=min)
t5++;
}
return uglyArray[n-1];
}
//比较三个数的大小
private int min(int i, int j, int k) {
int min = (i<j) ? i:j;
return (min<k) ? min:k;
}
}