Leetcode[263, 264] Ugly Number

###Task1 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.

###Python

class Solution(object):
    def isUgly(self, num):
        """
        :type num: int
        :rtype: bool
        """
        if num <= 0:
            return False
        while num % 2 == 0:
            num /= 2
        while num % 3 == 0:
            num /= 3
        while num % 5 == 0:
            num /= 5
        return num == 1

###Java

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

###Task2 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.

Hint:

The naive approach is to call isUgly for every number until you reach the nth one. Most numbers are not ugly. Try to focus your effort on generating only the ugly ones.

An ugly number must be multiplied by either 2, 3, or 5 from a smaller ugly number.

The key is how to maintain the order of the ugly numbers. Try a similar approach of merging from three sorted lists: L1, L2, and L3.

Assume you have Uk, the kth ugly number. Then Uk+1 must be Min(L1 * 2, L2 * 3, L3 * 5).

###Python

class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        ret = [1]
        twos = 0
        threes = 0
        fives = 0
        while len(ret) < n:
            next = min(ret[twos] * 2, ret[threes] * 3, ret[fives] * 5)
            if next == ret[twos] * 2:
                twos += 1
            if next == ret[threes] * 3:
                threes += 1
            if next == ret[fives] * 5:
                fives += 1
            ret.append(next)
        return ret[-1]

###Java

public class Solution {
    public int nthUglyNumber(int n) {
        if (n <= 0) {
            return 0;
        }
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        int p2 = 0;
        int p3 = 0;
        int p5 = 0;
        
        while (list.size() < n) {
            int next2 = list.get(p2) * 2;
            int next3 = list.get(p3) * 3;
            int next5 = list.get(p5) * 5;
            
            int curMin = Math.min(next2, Math.min(next3, next5));
            list.add(curMin);
            if (curMin == next2) {
                p2++;
            } 
            if (curMin == next3) {
                p3++;
            }
            if (curMin == next5) {
                p5++;
            }
        }
        
        return list.get(n - 1);
    }
}

###Points 丑陋数序列可以拆分为下面3个子列表:

(1) 1×2, 2×2, 3×2, 4×2, 5×2, …
(2) 1×3, 2×3, 3×3, 4×3, 5×3, …
(3) 1×5, 2×5, 3×5, 4×5, 5×5, …
我们可以发现每一个子列表都是丑陋数本身(1, 2, 3, 4, 5, …) 乘以 2, 3, 5

接下来我们使用与归并排序相似的合并方法,从3个子列表中获取丑陋数。每一步我们从中选出最小的一个,然后向后移动一步。