/**
* 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).
*
* Tags: Dynamic Programming, Heap, Math
*
* Similar Problems: (H) Merge k Sorted Lists, (E) Count Primes, (E) Ugly Number, (M) Perfect Squares, (M) Super Ugly
* Number
*/
public class UglyNumber2 {
public int nthUglyNumber(int n) {
if (n <= 0) return -1;
if (n == 1) return 1;
// pointers for 2, 3, 5
int p2 = 0;
int p3 = 0;
int p5 = 0;
// generate ugly numbers array
int[] uglyNums = new int[n];
uglyNums[0] = 1;
for (int i = 1; i < n; i++) {
uglyNums[i] = Math.min(uglyNums[p2] * 2, Math.min(uglyNums[p3] * 3, uglyNums[p5] * 5));
// update indices
if (uglyNums[i] == uglyNums[p2] * 2) p2++;
if (uglyNums[i] == uglyNums[p3] * 3) p3++;
if (uglyNums[i] == uglyNums[p5] * 5) p5++;
}
return uglyNums[n - 1];
}
}