
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:
- Initialize an array
ugly
whereugly[i]
will hold thei-th
ugly number. The first ugly number is 1, sougly[0] = 1
. - Use three indices
i2
,i3
, andi5
initialized to 0. These indices will track where we are for the multiples of 2, 3, and 5, respectively. - Use three variables
next_multiple_2
,next_multiple_3
, andnext_multiple_5
to store the next multiples of 2, 3, and 5. Initialize these to2 * ugly[i2]
,3 * ugly[i3]
, and5 * ugly[i5]
, respectively. - For each
k
from 1 ton-1
, do the following:- Find the smallest value among
next_multiple_2
,next_multiple_3
, andnext_multiple_5
and assign it tougly[k]
. - Increment the index corresponding to the smallest value (
i2
,i3
, ori5
). For example, ifnext_multiple_2
was the smallest, increasei2
by 1. - Recalculate the
next_multiple
for the indices that were updated.
- Find the smallest value among
- The value in
ugly[n-1]
will be our desirednth
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
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 toposition
and setting the first element to 1, as the first ugly number is always 1. - Maintain three pointers
ptr2
,ptr3
, andptr5
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
, andptr5
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.
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
, andnext5
represent the next potential ugly numbers from the respective sequences.
Key Steps in the Algorithm:
- Iterate from 1 to n-1 to fill the sequence array:
- Calculate the minimum of
next2
,next3
, andnext5
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 thesequence
array by 2, 3, or 5.
- Calculate the minimum of
- 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.
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 takescount
, an integer that represents the position of the ugly number to find.The method initializes a list
sequence
of lengthcount
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.
No comments yet.