题目描述
把只包含质因子2、3和5 的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
方法一:逐个判断每个整数是否是丑数(超时)
class Solution {
public int GetUglyNumber_Solution(int index) {
if(index<=0){
return 0;
}
int cnt=0;
int x=0;
while(cnt<index){
x++;
if(isUgly(x)){
cnt++;
}
}
return x;
}
//丑数只能被2、3、5整除,如果一个数能被2整数,我们把它连续除以2,如果能被3整除,连续除以3,如果能被5整除,连续除以5。如果最后得到1,那么这个数就是丑数。
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;
}
}
方法二:空间换时间
用一个数组装第 1-n 个丑数,从小到大排。
根据丑数的定义一个丑数应该是另一个丑数乘以 2、3或者 5 的结果(1除外)。
为了保持数组中丑数的顺序,每次添加的元素应该是之前所有元素的2、3、5的倍数,且大于上一个丑数,中最小的那个。
为了不遍历之前的所有丑数,定义三个指针,分别指向之前元素中2、3、5的倍数最有可能成为下一个丑数的元素的位置。
class Solution {
public int GetUglyNumber_Solution(int index) {
if (index <= 0) {
return 0;
}
int[] uglyN = new int[index];
uglyN[0] = 1;// 第一个丑数为1
int nextUglyN = 1;
int p2 = 0, p3 = 0, p5 = 0;
while (nextUglyN < index) {
int min = Math.min(Math.min(uglyN[p2] * 2, uglyN[p3] * 3), uglyN[p5] * 5);
uglyN[nextUglyN++] = min;
// 前移指针
while (uglyN[p2] * 2 <= min) {
p2++;
}
while (uglyN[p3] * 3 <= min) {
p3++;
}
while (uglyN[p5] * 5 <= min) {
p5++;
}
}
return uglyN[index - 1];// 因为下标从0开始存,第index个丑数下标为index-1
}
}