题目连接:
题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
数据范围:0≤n≤2000
要求:空间复杂度 O(n)O, 时间复杂度 O(n)
解题思路:
方案一:
首先一个简单方案,就是从1开始,一个一个的数去判断,但是这样会有性能问题,就是N=1500时输出值=859963392,则需要循环8E多次,效率太低。
方案二:
一个一个的找不行,那我们就换个思路,能不能通过2,3,5相互乘的组合来从小往大一个一个的找丑数。
丑数*2,*3,*5后一定还是丑数,那么根据这个,我们可以依次的从小到大找丑数。
三个变量i2,i3,i5用来记录
i2记录的是当前位置的丑数*2之后当前的最大值。记录的是i2位置的数乘以2之后参与比较的丑数。
i3,i5同理
我们的丑数数组是1,2,3,4,5,6,8,9,10,12...(从2开始的数组都是每轮运算加进来的)
我们可以这样比较,
第一轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于1*2,1*3,1*5比较,2最小,把2添加到丑数数组中,array[1]=2,则i2的位置由0变为1,此时array[i2]=2;
第二轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于2*2,1*3,1*5比较,3最小,把3添加到丑数数组中,array[2]=3,则i3的位置由0变为1,此时array[i3]=2;
第三轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于2*2,2*3,1*5比较,4最小,把4添加到丑数数组中,array[3]=4,则i2的位置由1变为2,此时array[i2]=3;
第四轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于2*4,2*3,1*5比较,5最小,把5添加到丑数数组中,array[4]=5,则i5的位置由0变为1,此时array[i5]=2;
第五轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于3*2,2*3,2*5比较,6最小,把6添加到丑数数组中,array[5]=6;,则i2的位置由2变为3,则i3的位置由1变为2,此时array[i2]=4,array[i3]=3;
第六轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于4*2,3*3,2*5比较,8最小,把8添加到丑数数组中,array[6]=8;,则i2的位置由3变为4,此时array[i2]=5;
继续第七轮,第八轮等等,每轮算出来的就是当前最小的丑数加入到数组当中。
代码
方案一代码:
Set<Integer> set = new HashSet<>();
//从小到大直接找
public int GetUglyNumber_Solution(int index) {
if (index <= 5) {
return index;
}
set.add(1);
set.add(2);
set.add(3);
set.add(4);
set.add(5);
int num = 5;
int i = 6;
while (num < index) {
if (isChoushu(i)) {
num++;
}
i++;
}
return --i;
}
private boolean isChoushu(int i) {
if (i % 2 == 0) {
if (set.contains(i / 2)) {
set.add(i);
return true;
}
}
if (i % 3 == 0) {
if (set.contains(i / 3)) {
set.add(i);
return true;
}
}
if (i % 5 == 0) {
if (set.contains(i / 5)) {
set.add(i);
return true;
}
}
return false;
}
方案二代码:
public int GetUglyNumber_Solution(int index) {
int i = 0;
int num2 = 0;
int num3 = 0;
int num5 = 0;
int[] result = new int[index];
result[0] = 1;
while (i++ < index - 1) {
int i2 = result[num2] * 2;
int i3 = result[num3] * 3;
int i5 = result[num5] * 5;
int min = Math.min(Math.min(i2, i3), i5);
result[i] = min;
if (min == i2) {
num2++;
}
if (min == i3) {
num3++;
}
if (min == i5) {
num5++;
}
}
return result[index - 1];
}