Super Ugly Number

Write a program to find the nth super ugly number.

Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers given primes = [2, 7, 13, 19] of size 4.

  • 1 is a super ugly number for any given primes.
  • The given numbers in primes are in ascending order.
  • 0 < k ≤ 100, 0 < n ≤ 10^6, 0 < primes[i] < 1000

Example:

Given n = 6, primes = [2, 7, 13, 19] return 13.

Solution:

Version 1: extension to Ugly Number II. Instead of using p2, p3, and p5, we use a pointer array. Better Solution

Version 2: similar to Kth Smallest Number in Sorted Matrix.

  • Step 1, create a PriorityQueue and a HashSet to store the found ugly numbers
  • Step 2, initialize them with 1 and all given primes. (primes[i] * 1 = primes[i])
  • Step 3, according to the definition of super ugly number (a positive numbers whose all prime factors are in the given list), we could have:
    • the next minimal ugly number is in the list of ( current minimal ugly number * each previously found guly number)

Code:

//version 1
public class Solution {

    public int nthSuperUglyNumber(int n, int[] primes) {
        if (primes == null || primes.length == 0) {
            return Integer.MIN_VALUE;
        }
        int[] ugly = new int[n];
        int[] idx = new int[primes.length];
        ugly[0] = 1;
        for (int i = 1; i < n; i++) {
            int min = Integer.MAX_VALUE;
            for (int j = 0; j < idx.length; j++) {
                min = Math.min(min, primes[j] * ugly[idx[j]]);
            }
            ugly[i] = min;
            for (int j = 0; j < idx.length; j++) {
                while (ugly[idx[j]] * primes[j] <= ugly[i]) {
                    idx[j]++;
                }
            }
        }
        return ugly[n - 1];
    }
}
//version 2
public class Solution {

    public int nthSuperUglyNumber(int k, int[] primes) {
        if (primes == null || primes.length == 0) {
            return Integer.MIN_VALUE;
        }
        int n = primes.length;
        Queue<Integer> q = new PriorityQueue<>(k * k + n);
        HashSet<Integer> visited = new HashSet<>();
        addHelper(1, 1, q, visited);
        for (int i = 0; i < n; i++) {
            addHelper(1, primes[i], q, visited);
        }
        List<Integer> list = new ArrayList<>();
        while (list.size() < k) {
            int min = q.poll();
            list.add(min);
            //add the product of current min with each other ugly number to the queue
            for (int x : list) {
                addHelper(x, min, q, visited);
            }
        }
        return list.get(list.size() - 1);
    }

    private void addHelper(int a, int b, Queue<Integer> q, 
                    HashSet<Integer> visited) {
        //double is used to avoid overflow
        double t = a;
        t = t * b;
        if (t >= Integer.MAX_VALUE) {
            return;
        }
        int p = a * b; 
        if (p < Integer.MAX_VALUE && !visited.contains(p)) {
            q.offer(p);
            visited.add(p);
        }
    }
}

results matching ""

    No results matching ""