Ugly Number II 4

Question

Ugly number is a number that only have factors 2, 3 and 5.

Design an algorithm to find the nth ugly number. The first 10 ugly numbers are 1, 2, 3, 4, 5, 6, 8, 9, 10, 12...

Notice

Note that 1 is typically treated as an ugly number.

Example

If n=9, return 10.

Challenge

O(n log n) or O(n) time.

Solution

方法一:HashMap + PriorityQueue(MinHeap):将2,3,5入队,每次取出堆顶元素(最小值),依次和3个factor相乘,将所得结果入队。用HashMap记录入队元素,入过队的元素不能再次入队。

方法二:以1为第一个元素,寻找比当前元素大的元素里面的最小者入队。每个factor用一个count来记录队列中第几个元素乘以factor以后恰好比current大,取3个factor结果里面的最小者作为下一个元素入队。

代码如下:

HashMap + Heap O(nlogn):

class Solution {
    /**
     * @param n an integer
     * @return the nth prime number as description.
     */
    public int nthUglyNumber(int n) {
        // Write your code here
        //HashMap + Heap O(nlogn)

        if(n <= 0){
            return 0;
        }

        PriorityQueue<Long> Q = new PriorityQueue<Long>();
        HashMap<Long, Boolean> inQ = new HashMap<Long, Boolean>();
        Long[] prime = new Long[3];
        prime[0] = Long.valueOf(2);
        prime[1] = Long.valueOf(3);
        prime[2] = Long.valueOf(5);
        for(int i = 0; i < 3; i++){
            Q.add(prime[i]);
            inQ.put(prime[i], true);
        }

        //每次取最小堆(优先队列)顶的元素,取n-1次,同时将取出的数和3个factor相乘的结果加入队列(如果本来已经在队列中则不用加)
        Long number = Long.valueOf(1);
        for(int i = 1; i < n; i++){
            number = Q.poll();
            for(int j = 0; j < 3; j++){
                if(!inQ.containsKey(number * prime[j])){
                    Q.add(number * prime[j]);
                    inQ.put(number * prime[j], true);
                }
            }
        }
        //Long转换为Int
        return number.intValue();
    }
}

O(n):

class Solution {
    /**
     * @param n an integer
     * @return the nth prime number as description.
     */
    public int nthUglyNumber(int n) {
        // Write your code here
        //O(n)
        ArrayList<Integer> ugly = new ArrayList<Integer>();
        ugly.add(1);
        int p1 = 0, p2 = 0, p3 = 0;
        int min1 = 0, min2 = 0, min3 = 0;
        int current = 1;

        //用current记录当前元素,寻找比当前元素大的数里面的最小值作为下一个元素
        while(ugly.size() < n){
            while(ugly.get(p1) * 2 < current){
                p1++;
            }
            min1 = ugly.get(p1) * 2;

            while(ugly.get(p2) * 3 < current){
                p2++;
            }
            min2 = ugly.get(p2) * 3;

            while(ugly.get(p3) * 5 < current){
                p3++;
            }
            min3 = ugly.get(p3) * 5;

            int next = Math.min(min1, min2);
            next = Math.min(next, min3);

            current = next + 1;
            ugly.add(next);
        }

        return ugly.get(n - 1);
    }
}

results matching ""

    No results matching ""