A clear explanation of Minimum Factorization using greedy digit factors from 9 down to 2.
Problem Restatement
We are given a positive integer num.
We need to find the smallest positive integer x such that the product of the digits of x equals num.
If no such integer exists, return 0.
If the answer does not fit in a 32-bit signed integer, return 0.
The official examples are:
num = 48Output:
68because:
6 * 8 == 48Another example:
num = 15Output:
35because:
3 * 5 == 15Source: LeetCode 625 asks for the smallest positive integer whose digit product equals the input, returning 0 if impossible or outside 32-bit signed integer range.
Input and Output
| Item | Meaning |
|---|---|
| Input | A positive integer num |
| Output | The smallest positive integer whose digits multiply to num |
| Impossible case | Return 0 |
| Overflow case | Return 0 if answer exceeds 32-bit signed integer range |
Example function shape:
def smallestFactorization(num: int) -> int:
...Examples
Example 1:
num = 48We can factor 48 as:
6 * 8 = 48So one valid number is:
68The answer is:
68Example 2:
num = 15We can factor 15 as:
3 * 5 = 15The smallest valid number is:
35Example 3:
num = 11There is no digit from 2 to 9 that can help build product 11.
The digit product cannot contain a prime factor 11.
So the answer is:
0Example 4:
num = 1The smallest positive integer whose digit product is 1 is:
1So the answer is:
1First Thought: Try All Numbers
A direct approach is to test numbers one by one.
For each number x, compute the product of its digits. If the product equals num, return x.
This is not practical.
The answer could be large, and checking every integer wastes time. We need to construct the answer from the factorization of num.
Key Insight
Every digit in the answer must be from 2 to 9, except for the special case num == 1.
The digit 1 does not change the product, but it makes the number longer and usually larger. So it is never useful for num > 1.
To make the final number as small as possible, we want as few digits as possible first. A number with fewer digits is smaller than any positive number with more digits, unless there are leading zeros, which we do not use here.
So we should use large digit factors whenever possible.
For example:
48 = 2 * 2 * 2 * 2 * 3This could give:
22223But we can combine factors into larger digits:
48 = 6 * 8This gives:
68So we greedily divide by digits from 9 down to 2.
After collecting the digits, we place them in ascending order to get the smallest number.
Algorithm
Handle the small case first.
If num == 1, return 1.
Then create an empty list called digits.
For each digit d from 9 down to 2:
- While
numis divisible byd, appenddtodigits. - Divide
numbyd.
After the loop:
- If
num != 1, then some factor could not be represented using digits2through9. Return0. - Reverse the collected digits so they are in ascending order.
- Convert them into an integer.
- If the integer is larger than
2^31 - 1, return0. - Otherwise return the integer.
Correctness
For num == 1, the smallest positive integer with digit product 1 is 1, so returning 1 is correct.
For num > 1, digit 1 is never useful because multiplying by 1 does not change the product and only adds another digit to the answer. Therefore every useful digit must be in the range 2 to 9.
The greedy step tries larger digits first. This minimizes the number of digits because a larger composite digit can replace several smaller factors. For example, using 8 is better than using 2, 2, 2, because it preserves the same product with fewer digits. Similarly, using 9 is better than using 3, 3.
After all possible divisions by digits 9 down to 2, if the remaining num is greater than 1, then it contains a factor that cannot be represented by any digit from 2 to 9. No valid integer can have that digit product, so returning 0 is correct.
If the remaining num is 1, then the collected digits multiply to the original input. The greedy process used the fewest possible digits because it always replaced factors with the largest valid digit whenever possible.
Among numbers with the same multiset of digits, the smallest integer is obtained by placing digits in ascending order. Since we collected digits from large to small, reversing them gives the smallest possible arrangement.
Therefore the algorithm returns the smallest valid integer when one exists, and returns 0 when no valid integer exists or when the answer exceeds the 32-bit signed integer limit.
Complexity
| Metric | Value | Why |
|---|---|---|
| Time | O(log num) | Each successful division reduces num by at least a factor of 2 |
| Space | O(log num) | We store the factor digits |
The loop checks only digits 9 through 2, so the number of digit choices is constant.
Implementation
class Solution:
def smallestFactorization(self, num: int) -> int:
if num == 1:
return 1
digits = []
for d in range(9, 1, -1):
while num % d == 0:
digits.append(d)
num //= d
if num != 1:
return 0
answer = 0
for d in reversed(digits):
answer = answer * 10 + d
if answer > 2**31 - 1:
return 0
return answerCode Explanation
The special case is handled first:
if num == 1:
return 1Then we collect digit factors:
digits = []We try digits from 9 down to 2:
for d in range(9, 1, -1):Whenever d divides num, we use it as one digit:
while num % d == 0:
digits.append(d)
num //= dThis extracts as many large digit factors as possible.
After the loop, if num is not 1, factorization failed:
if num != 1:
return 0Then we build the final number in ascending digit order:
for d in reversed(digits):
answer = answer * 10 + dThe digits were collected from large to small, so reversing gives small to large.
The overflow check is done while building the answer:
if answer > 2**31 - 1:
return 0If the number fits, we return it:
return answerTesting
def run_tests():
s = Solution()
assert s.smallestFactorization(48) == 68
assert s.smallestFactorization(15) == 35
assert s.smallestFactorization(1) == 1
assert s.smallestFactorization(11) == 0
assert s.smallestFactorization(36) == 49
assert s.smallestFactorization(100) == 455
assert s.smallestFactorization(2**31) == 0
print("all tests passed")
run_tests()Test meaning:
| Test | Why |
|---|---|
48 | Basic example with composite factors |
15 | Basic example using 3 and 5 |
1 | Special case |
11 | Impossible prime factor |
36 | Chooses 4 * 9, giving 49 |
100 | Builds 455, since 4 * 5 * 5 = 100 |
2^31 | Checks overflow behavior |