[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;
    }
}
posted @ 2020-09-12 10:13  消灭猕猴桃  阅读(53)  评论(0编辑  收藏  举报