[leetCode]剑指 Offer 49. 丑数
解法
直观解法是遍历数字,判断每个数字是否是丑数(连续除2或3或5最后等于1)。这种解法比较直观但是每个数字都需要计算耗时太大。
直观解法比较慢是由于每个数字都需要计算,我们可以考虑空间换时间来避免这种计算。定义一个数组,存放排序好的丑数,假设数组中某个位置的丑数是M,那么它肯定能由之前的丑数乘2或3或5得到。我们可以将M之前得丑数都乘2找到大于M得最小值M2,都乘3找到大于M的最小值M3,都乘5找到大于M的最小值M5,最后比较M2,M3,M5找到最小值作为下一个丑数。
这种方法M之前丑数都要乘2,3,5。我们可以知道在M之前肯定存在一个丑数T2,使得T2之前的丑数乘2都小于等于M,T2之后的都太大了。同理存在T3,T5,我们只需记录下这个丑数的位置,每次生成新丑数的时候更新这三个位置即可。
代码如下:
class Solution {
public int nthUglyNumber(int n) {
if(n <= 0)
return 0;
int[] uglyNumbers = new int[n];
uglyNumbers[0] = 1;
int t2 = 0;
int t3 = 0;
int t5 = 0;
int nextUglyNumber = 1;
while(nextUglyNumber < n) {
int min = min(uglyNumbers[t2]*2, uglyNumbers[t3]*3, uglyNumbers[t5]*5);
uglyNumbers[nextUglyNumber] = min;
while(uglyNumbers[t2]*2 <= uglyNumbers[nextUglyNumber])
t2++;
while(uglyNumbers[t3]*3 <= uglyNumbers[nextUglyNumber])
t3++;
while(uglyNumbers[t5]*5 <= uglyNumbers[nextUglyNumber])
t5++;
nextUglyNumber++;
}
return uglyNumbers[nextUglyNumber-1];
}
private int min(int num1, int num2, int num3) {
int min = num1 < num2 ? num1 : num2;
return min < num3 ? min : num3;
}
}