625. Minimum Factorization 🔒
Problem Description
Given a positive integer num
, you need to find the smallest positive integer x
such that when you multiply all the digits of x
together, you get num
.
For example:
- If
num = 48
, the answer would be68
because6 × 8 = 48
- If
num = 15
, the answer would be35
because3 × 5 = 15
The key requirements are:
- Find the smallest such integer
x
- The product of all digits in
x
must equalnum
- If no valid answer exists, return
0
- If the answer exceeds the range of a 32-bit signed integer (greater than
2^31 - 1
), return0
Special cases to consider:
- If
num
is 0, the answer is10
(since1 × 0 = 0
) - If
num
is 1, the answer is1
itself - If
num
contains prime factors other than 2, 3, 5, or 7, no valid answer exists (since digits can only be 1-9)
The solution works by greedily using the largest possible digits (9 down to 2) to factorize num
, building the result from right to left to ensure the smallest possible number.
Intuition
To get the smallest number whose digits multiply to num
, we need to think about what digits we can use and how to arrange them.
First, realize that we can only use digits 1-9 (0 would make the product 0). Since we want the smallest number, we want:
- Fewer digits - A 2-digit number is smaller than a 3-digit number
- Smaller leading digits - 234 is smaller than 432
The key insight is that to minimize the number of digits, we should use the largest possible digits. For example, if num = 24
, we could use:
2 × 2 × 2 × 3 = 24
giving us2223
(4 digits)4 × 6 = 24
giving us46
(2 digits)3 × 8 = 24
giving us38
(2 digits)
Between 46
and 38
, we choose 38
because it's smaller.
This leads to our strategy: greedily extract the largest possible factors from 9 down to 2. Why this order?
- Using larger digits reduces the total number of digits needed
- By processing from 9 to 2, we ensure we use the maximum possible large digits
When building the answer, we place larger digits at the end (rightmost positions). This seems counterintuitive, but it ensures the smallest final number. For example, if we need digits 3 and 8:
- Placing 8 first then 3:
83
- Placing 3 first then 8:
38
✓ (smaller)
The algorithm naturally handles this by building the number from right to left using ans = mul * i + ans
, where each new digit i
is placed to the left of previously added digits.
If after extracting all factors from 2-9, num
is still greater than 1, it means num
has prime factors larger than 7 (like 11, 13, etc.), which cannot be represented as single digits. In this case, no valid answer exists.
Solution Approach
The implementation follows a greedy factorization approach:
-
Handle edge cases: If
num < 2
, returnnum
directly. This covers cases wherenum = 0
ornum = 1
. -
Initialize variables:
ans = 0
: Stores the result number being builtmul = 1
: A multiplier to help place digits in correct positions
-
Greedy factorization loop: Iterate through digits from 9 down to 2:
for i in range(9, 1, -1): while num % i == 0: num //= i ans = mul * i + ans mul *= 10
For each digit
i
:- Check if
i
dividesnum
evenly usingnum % i == 0
- If yes, extract this factor:
num //= i
- Add digit
i
to the left of current answer:ans = mul * i + ans
- Update multiplier:
mul *= 10
to shift position for next digit
The formula
ans = mul * i + ans
effectively places the new digiti
at the leftmost available position. For example:- Initially:
ans = 0
,mul = 1
- Adding digit 8:
ans = 1 * 8 + 0 = 8
,mul = 10
- Adding digit 6:
ans = 10 * 6 + 8 = 68
,mul = 100
- Check if
-
Validation check: After the loop, verify:
num < 2
: Ensures all factors were extracted (no prime factors > 7 remain)ans <= 2**31 - 1
: Ensures the answer fits in a 32-bit signed integer
If both conditions are met, return
ans
; otherwise return0
.
The algorithm's correctness relies on:
- Processing larger digits first minimizes the total number of digits
- Building from right to left ensures the smallest numerical value
- The greedy approach guarantees the optimal solution because using the largest possible factors at each step minimizes both digit count and the resulting number's value
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's trace through the algorithm with num = 48
:
Initial State:
num = 48
ans = 0
(our result number)mul = 1
(position multiplier)
Iteration Process (from digit 9 down to 2):
-
Check digit 9:
48 % 9 = 3
(not divisible) → skip -
Check digit 8:
48 % 8 = 0
(divisible!)- Extract factor:
num = 48 ÷ 8 = 6
- Add digit 8 to answer:
ans = 1 × 8 + 0 = 8
- Update multiplier:
mul = 10
- Check again:
6 % 8 = 6
(not divisible) → move to next digit
- Extract factor:
-
Check digit 7:
6 % 7 = 6
(not divisible) → skip -
Check digit 6:
6 % 6 = 0
(divisible!)- Extract factor:
num = 6 ÷ 6 = 1
- Add digit 6 to answer:
ans = 10 × 6 + 8 = 68
- Update multiplier:
mul = 100
- Check again:
1 % 6 = 1
(not divisible) → move to next digit
- Extract factor:
-
Check digits 5, 4, 3, 2:
num = 1
, so none divide evenly → skip all
Final Validation:
num = 1 < 2
✓ (all factors extracted successfully)ans = 68 ≤ 2^31 - 1
✓ (within integer range)
Result: Return 68
Verification: 6 × 8 = 48
✓
Notice how the algorithm builds the number from right to left: first placing 8, then placing 6 to its left, creating the smallest possible number whose digits multiply to 48.
Solution Implementation
1class Solution:
2 def smallestFactorization(self, num: int) -> int:
3 # Special case: if num is 0 or 1, return it directly
4 if num < 2:
5 return num
6
7 # Initialize result and position multiplier
8 result = 0
9 position_multiplier = 1
10
11 # Try to factorize using digits from 9 to 2 (largest to smallest)
12 # This ensures we get the smallest possible number
13 for digit in range(9, 1, -1):
14 # Keep dividing by current digit while it's a factor
15 while num % digit == 0:
16 num //= digit
17 # Build the result by adding digits from right to left
18 result = position_multiplier * digit + result
19 position_multiplier *= 10
20
21 # Check if factorization is complete (num reduced to 1)
22 # and result doesn't overflow 32-bit signed integer
23 if num < 2 and result <= 2**31 - 1:
24 return result
25 else:
26 return 0
27
1class Solution {
2 public int smallestFactorization(int num) {
3 // Special case: single digit numbers return themselves
4 if (num < 2) {
5 return num;
6 }
7
8 // Use long to avoid overflow during construction
9 long result = 0;
10 long placeValue = 1; // Tracks the decimal place (1, 10, 100, ...)
11
12 // Try factoring with digits from 9 down to 2
13 // Starting from 9 ensures we use larger digits first,
14 // which gives us the smallest possible number
15 for (int digit = 9; digit >= 2; digit--) {
16 // Check if current digit is a factor
17 if (num % digit == 0) {
18 // Extract all occurrences of this factor
19 while (num % digit == 0) {
20 num /= digit;
21
22 // Place this digit in the result
23 // Larger digits go to rightmost positions for smallest number
24 result = placeValue * digit + result;
25 placeValue *= 10;
26 }
27 }
28 }
29
30 // Check if factorization was successful:
31 // - num should be 1 (completely factored using digits 2-9)
32 // - result should fit in Integer range
33 return (num < 2 && result <= Integer.MAX_VALUE) ? (int) result : 0;
34 }
35}
36
1class Solution {
2public:
3 int smallestFactorization(int num) {
4 // Special case: single digit numbers return themselves
5 // 0 -> 0, 1 -> 1
6 if (num < 2) {
7 return num;
8 }
9
10 // Build the result number from right to left
11 // result stores the final number, placeValue tracks the current digit position
12 long long result = 0;
13 long long placeValue = 1;
14
15 // Try to factorize using digits from 9 down to 2
16 // Starting from 9 ensures we use larger digits first, giving smaller result
17 for (int digit = 9; digit >= 2; --digit) {
18 // Check if current digit is a factor
19 if (num % digit == 0) {
20 // Extract all occurrences of this factor
21 while (num % digit == 0) {
22 num /= digit;
23 // Add the digit to the result at the current position
24 result = placeValue * digit + result;
25 // Move to the next digit position (tens, hundreds, etc.)
26 placeValue *= 10;
27 }
28 }
29 }
30
31 // Check if factorization was successful:
32 // 1. num should be 1 (completely factorized using digits 2-9)
33 // 2. result should not overflow integer range
34 return (num < 2 && result <= INT_MAX) ? result : 0;
35 }
36};
37
1function smallestFactorization(num: number): number {
2 // Special case: single digit numbers return themselves
3 // 0 -> 0, 1 -> 1
4 if (num < 2) {
5 return num;
6 }
7
8 // Build the result number from right to left
9 // result stores the final number, placeValue tracks the current digit position
10 let result: number = 0;
11 let placeValue: number = 1;
12
13 // Try to factorize using digits from 9 down to 2
14 // Starting from 9 ensures we use larger digits first, giving smaller result
15 for (let digit = 9; digit >= 2; digit--) {
16 // Check if current digit is a factor
17 if (num % digit === 0) {
18 // Extract all occurrences of this factor
19 while (num % digit === 0) {
20 num = Math.floor(num / digit);
21 // Add the digit to the result at the current position
22 result = placeValue * digit + result;
23 // Move to the next digit position (tens, hundreds, etc.)
24 placeValue *= 10;
25 }
26 }
27 }
28
29 // Check if factorization was successful:
30 // 1. num should be 1 (completely factorized using digits 2-9)
31 // 2. result should not overflow integer range (2^31 - 1 = 2147483647)
32 return (num < 2 && result <= 2147483647) ? result : 0;
33}
34
Time and Space Complexity
Time Complexity: O(log num)
The algorithm iterates through digits 9 to 2 (a constant 8 iterations in the outer loop). For each digit i
, the inner while loop divides num
by i
as many times as possible. The total number of divisions across all digits is bounded by log num
because we're repeatedly dividing the input number until it becomes less than 2. Each division operation takes O(1)
time. Therefore, the overall time complexity is O(log num)
.
Space Complexity: O(1)
The algorithm uses only a constant amount of extra space. The variables ans
, mul
, and i
are the only additional storage used, and they don't depend on the input size. No additional data structures like arrays or recursion stacks are used. Therefore, the space complexity is O(1)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Handling of Single-Digit Numbers
A common mistake is not properly handling when num
itself is a single digit (2-9). The algorithm might unnecessarily try to factorize these numbers when they should be returned directly.
Pitfall Example:
# Incorrect: This would return 0 for num = 7 if num < 2: return num # ... factorization logic ... # After loop, num = 7 (not reduced to 1), so returns 0
Solution: Add a check for single-digit numbers before starting factorization:
if num < 10: return num
2. Building the Number in Wrong Order
Many implementations mistakenly build the number from left to right or use string concatenation, leading to larger results.
Pitfall Example:
# Wrong approach - builds left to right
result = 0
for digit in range(9, 1, -1):
while num % digit == 0:
num //= digit
result = result * 10 + digit # This gives larger numbers!
For num = 48
: This would produce 86
instead of 68
.
Solution:
Always build from right to left using the formula result = position_multiplier * digit + result
.
3. Missing Integer Overflow Check
Forgetting to check if the result exceeds the 32-bit signed integer limit (2^31 - 1 = 2147483647
) can lead to incorrect outputs on platforms with strict integer bounds.
Pitfall Example:
# Missing overflow check if num == 1: # Only checking if factorization is complete return result
Solution: Always include the overflow check:
if num < 2 and result <= 2**31 - 1: return result
4. Incorrect Validation of Complete Factorization
Using num == 1
instead of num < 2
for the final check can cause issues with the edge case where num = 0
.
Pitfall Example:
# Wrong: This fails for num = 0 if num == 1 and result <= 2**31 - 1: return result
Solution:
Use num < 2
to handle both num = 1
(successful factorization) and num = 0
(edge case).
5. Not Handling num = 0 Correctly
The problem states that for num = 0
, the answer should be 10
(since 1 × 0 = 0
). However, the standard algorithm returns 0
directly for num < 2
.
Pitfall Example:
The current implementation returns 0
when num = 0
, but according to the problem description, it should return 10
.
Solution:
Add explicit handling for num = 0
:
if num == 0: return 10 if num == 1: return 1
What does the following code do?
1def f(arr1, arr2):
2 i, j = 0, 0
3 new_arr = []
4 while i < len(arr1) and j < len(arr2):
5 if arr1[i] < arr2[j]:
6 new_arr.append(arr1[i])
7 i += 1
8 else:
9 new_arr.append(arr2[j])
10 j += 1
11 new_arr.extend(arr1[i:])
12 new_arr.extend(arr2[j:])
13 return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2 int i = 0, j = 0;
3 List<Integer> newArr = new ArrayList<>();
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.add(arr1[i]);
8 i++;
9 } else {
10 newArr.add(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.add(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.add(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
1function f(arr1, arr2) {
2 let i = 0, j = 0;
3 let newArr = [];
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.push(arr1[i]);
8 i++;
9 } else {
10 newArr.push(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.push(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.push(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!