输出第n个丑数

方法一:暴力法

代码如下:

判断是否是丑数
public static boolean isUgly(int n){
        while(n!=1){
            if(n%2 == 0){
                n /= 2;
            }else if(n%3 == 0){
                n /= 3;
            }else if(n%5 == 0){
                n /= 5;
            }else{
                break;
            }
        }
        return n==1;
    }
public static int getUglyNumber(int n){
    if(n == 0) return 0;
    int count = 0;
    for(int i = 1;i<Integer.MAX_VALUE;i++){
        if(isUgly(i))
            count++;
        if(count == n)
            return i;
    }
    return 0;
}

方法二:思路:

三指针法。只计算丑数,而不计算非丑数。丑数=丑数*(2/3/5),所以创建数组保存有序的丑数。
关键在于如何在计算丑数的过程中保持数组有序。当前的丑数必然是之前某一个丑数*因子的结果,
但是不需要每个数都要乘一遍2、3、5。要获得的丑数必然是大于现在已有的,
在计算得出丑数中选择一个最小的放入数组中,来保持数组的有序,因为新放入的丑数是根据之前的丑数计算得到的,
所以必然是有序的。为了每次新得到的三个丑数都是比已有丑数大,且最小,所以要记录各个因子下次计算要使用的已有丑数在什么位置,
否则就会出现跳数,比如已有{1,2,3,4},我们知道下一个丑数应该是5,但是如果因子5没有选择第一个丑数1来相乘,就会漏掉5这个丑数。

代码实现如下:
public static int getUglyNumber(int n) {
        if(n == 0) return 0;
        //定义三个指针,分别指向质因子2,3,5
        int a = 0;
        int b = 0;
        int c = 0;
        int[] arr = new int[n];
        arr[0] = 1;
        for(int i = 1;i<n;i++){
            int r = arr[a]*2;
            int s = arr[b]*3;
            int t = arr[c]*5;
            int sign = Math.min(r,Math.min(s,t));
            //将最小的丑数放入结果集中,用于下一次计算
            arr[i] = sign;
            //找出对应此次计算最小丑数的因子,并移动指针指向下一次计算丑数对应的老丑数下标
            if(sign%2==0){
                a++;
            }
            if(sign%3==0){
                b++;
            }
            if(sign%5==0){
                c++;
            }
        }
        return arr[n-1];
    }
原文地址:https://www.cnblogs.com/du001011/p/10720987.html