Ugly Number II

Updated on 27 June, 2025
Ugly Number II header image

Problem Statement

In the realm of number theory, an ugly number is defined as a positive integer whose only prime factors are 2, 3, or 5. The concept centers around simplicity in the factorization, eschewing a more diverse set of prime divisors for just these three.

The task is to find the nth ugly number for a given integer n. This problem requires a method to sequentially generate these numbers until the nth one is determined, based on their unique factorization properties.

Examples

Example 1

Input:

n = 10

Output:

12

Explanation:

[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] is the sequence of the first 10 ugly numbers.

Example 2

Input:

n = 1

Output:

1

Explanation:

1 has no prime factors, therefore all of its prime factors are limited to 2, 3, and 5.

Constraints

  • 1 <= n <= 1690

Approach and Intuition

To achieve the solution for finding the nth ugly number, one can employ a dynamic programming technique. The intuition stems from the fact that every ugly number must be a multiple of either 2, 3, or 5 of a smaller ugly number. This understanding allows us to generate the sequence of ugly numbers systematically. Here's a breakdown of the approach:

  1. Initialize an array ugly where ugly[i] will hold the i-th ugly number. The first ugly number is 1, so ugly[0] = 1.
  2. Use three indices i2, i3, and i5 initialized to 0. These indices will track where we are for the multiples of 2, 3, and 5, respectively.
  3. Use three variables next_multiple_2, next_multiple_3, and next_multiple_5 to store the next multiples of 2, 3, and 5. Initialize these to 2 * ugly[i2], 3 * ugly[i3], and 5 * ugly[i5], respectively.
  4. For each k from 1 to n-1, do the following:
    • Find the smallest value among next_multiple_2, next_multiple_3, and next_multiple_5 and assign it to ugly[k].
    • Increment the index corresponding to the smallest value (i2, i3, or i5). For example, if next_multiple_2 was the smallest, increase i2 by 1.
    • Recalculate the next_multiple for the indices that were updated.
  5. The value in ugly[n-1] will be our desired nth ugly number.

This method ensures that we are constructing the sequence in an optimal way, by leveraging the fact that each new ugly number is derived from multiplying a previous ugly number by either 2, 3, or 5. The choice of selecting the minimum ensures that we get them in the correct order without gaps or repeats.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int findNthUglyNumber(int position) {
        vector<int> uglySequence(position);
        uglySequence[0] = 1;
    
        int ptr2 = 0, ptr3 = 0, ptr5 = 0;
        int value2 = 2, value3 = 3, value5 = 5;
    
        for (int index = 1; index < position; index++) {
            int minUgly = min(value2, min(value3, value5));
            uglySequence[index] = minUgly;
    
            if (minUgly == value2) {
                ptr2++;
                value2 = uglySequence[ptr2] * 2;
            }
            if (minUgly == value3) {
                ptr3++;
                value3 = uglySequence[ptr3] * 3;
            }
            if (minUgly == value5) {
                ptr5++;
                value5 = uglySequence[ptr5] * 5;
            }
        }
    
        return uglySequence[position - 1];
    }
};

The Ugly Number II problem involves finding the n-th ugly number using the C++ programming language. An ugly number is defined as a positive integer whose prime factors are limited to 2, 3, or 5.

The provided C++ solution uses dynamic programming to generate ugly numbers in a systematic manner. The core concept behind the solution is:

  • Start by initializing a vector uglySequence with the size equal to position and setting the first element to 1, as the first ugly number is always 1.
  • Maintain three pointers ptr2, ptr3, and ptr5 which are associated respectively with factors 2, 3, and 5. These pointers will help us select the next ugly number by multiplying the pointed index's element with 2, 3, and 5.
  • As you progress through the numbers, calculate potential candidates for the next ugly number by multiplying the values pointed by ptr2, ptr3, and ptr5 with 2, 3, and 5 respectively.
  • Determine the minimum value among these candidates and add it to uglySequence.
  • Increment the respective pointers when their candidate value is chosen as the minimum to avoid duplication of the same values.

This method ensures that each next ugly number is the smallest possible new ugly number and efficiently computes the position-th ugly number, which is uglySequence[position - 1].

By using this approach, time is not wasted checking non-ugly numbers and the solutions collector progresses in an optimal manner only considering viable next options.

java
class Solution {
    
    public int findNthUglyNumber(int n) {
        int[] sequence = new int[n]; // Array to hold the ugly numbers
        sequence[0] = 1; // Initializing the first element
    
        // Indices for the multiples of 2, 3, and 5
        int multiple2Index = 0, multiple3Index = 0, multiple5Index = 0;
        int next2 = 2, next3 = 3, next5 = 5;
    
        // Loop to fill in values up to the nth ugly number
        for (int i = 1; i < n; i++) {
            // Determine the next number to add to the sequence
            int minUgly = Math.min(next2, Math.min(next3, next5));
            sequence[i] = minUgly;
    
            // Advance the necessary pointers
            if (minUgly == next2) {
                multiple2Index++;
                next2 = sequence[multiple2Index] * 2;
            }
            if (minUgly == next3) {
                multiple3Index++;
                next3 = sequence[multiple3Index] * 3;
            }
            if (minUgly == next5) {
                multiple5Index++;
                next5 = sequence[multiple5Index] * 5;
            }
        }
    
        return sequence[n - 1]; // Return the nth ugly number
    }
}

The provided Java solution implements an algorithm to find the nth ugly number. Ugly numbers are positive integers that only have prime factors of 2, 3, or 5.

Understanding the Code Structure:

  • An array, sequence, stores the first n ugly numbers.
  • Initialization: The first ugly number, 1, is directly assigned.
  • Three pointers (multiple2Index, multiple3Index, multiple5Index) track the position in the ugly number sequence for multiplying by 2, 3, and 5, respectively.
  • Variables next2, next3, and next5 represent the next potential ugly numbers from the respective sequences.

Key Steps in the Algorithm:

  1. Iterate from 1 to n-1 to fill the sequence array:
    • Calculate the minimum of next2, next3, and next5 to determine the next ugly number.
    • Update the array with this minimum value.
    • Depending on which minimum value was chosen, increment the respective index and update the next variable by multiplying the new value from the sequence array by 2, 3, or 5.
  2. Return the nth element of the sequence array, which is the nth ugly number.

This method efficiently calculates ugly numbers without multiplication of non-ugly numbers by maintaining three streams of potential candidates, reducing unnecessary computations.

python
class Solution:
    def getUglyNumber(self, count: int) -> int:
        sequence = [0] * count  
        sequence[0] = 1  
    
        idx2, idx3, idx5 = 0, 0, 0
        mult2, mult3, mult5 = 2, 3, 5
    
        for index in range(1, count):
            next_value = min(mult2, mult3, mult5)
            sequence[index] = next_value
    
            if next_value == mult2:
                idx2 += 1
                mult2 = sequence[idx2] * 2
            if next_value == mult3:
                idx3 += 1
                mult3 = sequence[idx3] * 3
            if next_value == mult5:
                idx5 += 1
                mult5 = sequence[idx5] * 5
    
        return sequence[count - 1]

The given code in Python provides a method to find the nth "ugly number". Ugly numbers are positive numbers whose only prime factors are 2, 3, or 5. Here's how this solution works:

  • A class called Solution contains a method, getUglyNumber, which takes count, an integer that represents the position of the ugly number to find.

  • The method initializes a list sequence of length count to store the sequence of ugly numbers, with the first element initialized to 1 since the first ugly number is 1.

  • It sets three indices (idx2, idx3, idx5) to zero, which are used to track positions in the array for multiplication with 2, 3, and 5, respectively.

  • Corresponding multiplication values (mult2, mult3, mult5) are initialized to 2, 3, and 5.

  • A loop iterates through positions from the second position to the last in the sequence. At each position:

    • It finds the minimum of the multiplication values to determine the next ugly number.
    • This number is added to the sequence.
    • It then updates the indices and multipliers for future positions based on which base (2, 3, or 5) was used to generate the current ugly number.
  • Finally, the nth ugly number (position count - 1 in the zero-indexed list) is returned.

This approach ensures the efficient calculation of ugly numbers using dynamic programming principles, particularly by maintaining a sequence and updating it based on previously found ugly numbers.

Comments

No comments yet.