剑指offer-34.丑数

https://www.nowcoder.com/practice/6aa9e04fc3794f68acf8778237ba065b?tpId=13&tqId=11186&tPage=2&rp=1&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking

题目描述
把只包含质因子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
    }
}

猜你喜欢

转载自blog.csdn.net/zxm1306192988/article/details/81167590