[Leetcode] Ugly Number 丑陋数

628 查看

Ugly Number I

Write a program to check whether a given number is an ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7.

Note that 1 is typically treated as an ugly number.

原题链接

因式分解法

复杂度

时间 O(logN) 空间 O(1)

思路

根据丑陋数的定义,我们将给定数除以2、3、5,直到无法整除,也就是除以2、3、5的余数不再为0时停止。这时如果得到1,说明是所有因子都是2或3或5,如果不是1,则不是丑陋数。

代码

public class Solution {
    public boolean isUgly(int num) {
        if(num == 0){
            return false;
        }
        int rem2 = num % 2;
        int rem3 = num % 3;
        int rem5 = num % 5;
        while(rem2 == 0 || rem3 == 0 || rem5 == 0){
            if(rem2 == 0){
                num = num / 2;
            } else if(rem3 == 0){
                num = num / 3;
            } else {
                num = num / 5;
            }
            rem2 = num % 2;
            rem3 = num % 3;
            rem5 = num % 5;
        }
        return num == 1;
    }
}

简洁版

for (int i=2; i<6 && num>0; i++)
    while (num % i == 0)
        num /= i;
return num == 1;

Ugly Number II

Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note that 1 is typically treated as an ugly number.

原题链接

动态规划

复杂度

时间 O(N) 空间 O(N)

思路

要得到第N个丑陋数,最直接的想法就是从1开始递增循环,直到找到第N个丑陋数,但是这样明显开销太大,而且我们没有用到已经生成的丑陋数的信息。如果有一个方法能够顺序只生成丑陋数就好了。仔细观察可以发现,丑陋数的因子也必定是丑陋数,它一定是某个丑陋数乘2、3、5得到的。但问题在于,小的丑陋数乘5不一定比大的丑陋数乘2要小,我们没法直接使用目前最大的丑陋数来乘2、3、5顺序得到更大的丑陋数。不过,我们可以确定的是,小的丑陋数乘2,肯定小于大的丑陋数乘2。所以我们使用三个指针,分别记录乘2、3、5得出的目前最大丑陋数,这样我们通过比较这三种最大丑陋数(这里最大是相对于只乘2、只乘3、只乘5三种不同情况下最大的丑陋数),就得到了所有数里最大的丑陋数。

代码

public class Solution {
    public int nthUglyNumber(int n) {
        List<Integer> res = new ArrayList<Integer>();
        res.add(1);
        int i2 = 0, i3 = 0, i5 = 0;
        while(res.size() < n){
            int m2 = res.get(i2) * 2;
            int m3 = res.get(i3) * 3;
            int m5 = res.get(i5) * 5;
            int min = Math.min(m2, Math.min(m3, m5));
            res.add(min);
            if(min == m2) i2++;
            if(min == m3) i3++;
            if(min == m5) i5++;
        }
        return res.get(res.size()-1);
    }
}