Overflow in intermediate arithmetic
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
You are given a string num which represents a positive integer, and an integer t.
A number is called zero-free if none of its digits are 0.
Return a string representing the smallest zero-free number greater than or equal to num such that the product of its digits is divisible by t. If no such number exists, return "-1".
Example 1:
Input: num = "1234", t = 256
Output: "1488"
Explanation:
The smallest zero-free number that is greater than 1234 and has the product of its digits divisible by 256 is 1488, with the product of its digits equal to 256.
Example 2:
Input: num = "12355", t = 50
Output: "12355"
Explanation:
12355 is already zero-free and has the product of its digits divisible by 50, with the product of its digits equal to 150.
Example 3:
Input: num = "11111", t = 26
Output: "-1"
Explanation:
No number greater than 11111 has the product of its digits divisible by 26.
Constraints:
2 <= num.length <= 2 * 105num consists only of digits in the range ['0', '9'].num does not contain leading zeros.1 <= t <= 1014Problem summary: You are given a string num which represents a positive integer, and an integer t. A number is called zero-free if none of its digits are 0. Return a string representing the smallest zero-free number greater than or equal to num such that the product of its digits is divisible by t. If no such number exists, return "-1".
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Math · Backtracking · Greedy
"1234" 256
"12355" 50
"11111" 26
smallest-number-with-given-digit-product)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3348: Smallest Divisible Digit Product II
class Solution {
public String smallestNumber(String num, long t) {
Pair<Map<Integer, Integer>, Boolean> primeCountResult = getPrimeCount(t);
Map<Integer, Integer> primeCount = primeCountResult.getKey();
boolean isDivisible = primeCountResult.getValue();
if (!isDivisible)
return "-1";
Map<Integer, Integer> factorCount = getFactorCount(primeCount);
if (sumValues(factorCount) > num.length())
return construct(factorCount);
Map<Integer, Integer> primeCountPrefix = getPrimeCount(num);
int firstZeroIndex = num.indexOf('0');
if (firstZeroIndex == -1) {
firstZeroIndex = num.length();
if (isSubset(primeCount, primeCountPrefix))
return num;
}
for (int i = num.length() - 1; i >= 0; --i) {
final int d = num.charAt(i) - '0';
// Remove the current digit's factors from primeCountPrefix.
primeCountPrefix = subtract(primeCountPrefix, FACTOR_COUNTS.get(d));
final int spaceAfterThisDigit = num.length() - 1 - i;
if (i > firstZeroIndex)
continue;
for (int biggerDigit = d + 1; biggerDigit < 10; ++biggerDigit) {
// Compute the required factors after replacing with a larger digit.
Map<Integer, Integer> factorsAfterReplacement = getFactorCount(
subtract(subtract(primeCount, primeCountPrefix), FACTOR_COUNTS.get(biggerDigit)));
// Check if the replacement is possible within the available space.
if (sumValues(factorsAfterReplacement) <= spaceAfterThisDigit) {
// Fill extra space with '1', if any, and construct the result.
final int fillOnes = spaceAfterThisDigit - sumValues(factorsAfterReplacement);
return num.substring(0, i) + // Keep the prefix unchanged.
biggerDigit + // Replace the current digit.
"1".repeat(fillOnes) + // Fill remaining space with '1'.
construct(factorsAfterReplacement);
}
}
}
// No solution of the same length exists, so we need to extend the number
// by prepending '1's and adding the required factors.
Map<Integer, Integer> factorsAfterExtension = getFactorCount(primeCount);
return "1".repeat(num.length() + 1 - sumValues(factorsAfterExtension)) +
construct(factorsAfterExtension);
}
private static final Map<Integer, Map<Integer, Integer>> FACTOR_COUNTS = Map.of(
0, Map.of(), 1, Map.of(), 2, Map.of(2, 1), 3, Map.of(3, 1), 4, Map.of(2, 2), 5, Map.of(5, 1),
6, Map.of(2, 1, 3, 1), 7, Map.of(7, 1), 8, Map.of(2, 3), 9, Map.of(3, 2));
// Returns the prime count of t and if t is divisible by 2, 3, 5, 7.
private Pair<Map<Integer, Integer>, Boolean> getPrimeCount(long t) {
Map<Integer, Integer> count = new HashMap<>(Map.of(2, 0, 3, 0, 5, 0, 7, 0));
for (int prime : new int[] {2, 3, 5, 7}) {
while (t % prime == 0) {
t /= prime;
count.put(prime, count.get(prime) + 1);
}
}
return new Pair<>(count, t == 1);
}
// Returns the prime count of `num`.
private Map<Integer, Integer> getPrimeCount(String num) {
Map<Integer, Integer> count = new HashMap<>(Map.of(2, 0, 3, 0, 5, 0, 7, 0));
for (final char c : num.toCharArray()) {
Map<Integer, Integer> digitFactors = FACTOR_COUNTS.get(c - '0');
for (Map.Entry<Integer, Integer> entry : digitFactors.entrySet()) {
final int prime = entry.getKey();
final int freq = entry.getValue();
count.merge(prime, freq, Integer::sum);
}
}
return count;
}
private Map<Integer, Integer> getFactorCount(Map<Integer, Integer> count) {
// 2^3 = 8
final int count8 = count.get(2) / 3;
final int remaining2 = count.get(2) % 3;
// 3^2 = 9
final int count9 = count.get(3) / 2;
int count3 = count.get(3) % 2;
// 2^2 = 4
int count4 = remaining2 / 2;
int count2 = remaining2 % 2;
// Combine 2 and 3 to 6 if both are present
int count6 = 0;
if (count2 == 1 && count3 == 1) {
count2 = 0;
count3 = 0;
count6 = 1;
}
// Combine 3 and 4 to 2 and 6 if both are present
if (count3 == 1 && count4 == 1) {
count2 = 1;
count6 = 1;
count3 = 0;
count4 = 0;
}
return Map.of(2, count2, 3, count3, 4, count4, 5, count.get(5), 6, count6, 7, count.get(7), 8,
count8, 9, count9);
}
private String construct(Map<Integer, Integer> factors) {
StringBuilder sb = new StringBuilder();
for (int digit = 2; digit < 10; ++digit)
sb.append(String.valueOf(digit).repeat(factors.get(digit)));
return sb.toString();
}
// Returns true if a is a subset of b.
private boolean isSubset(Map<Integer, Integer> a, Map<Integer, Integer> b) {
for (Map.Entry<Integer, Integer> entry : a.entrySet())
if (b.get(entry.getKey()) < entry.getValue())
return false;
return true;
}
// Returns a - b.
private Map<Integer, Integer> subtract(Map<Integer, Integer> a, Map<Integer, Integer> b) {
Map<Integer, Integer> res = new HashMap<>(a);
for (Map.Entry<Integer, Integer> entry : b.entrySet()) {
final int key = entry.getKey();
final int value = entry.getValue();
res.put(key, Math.max(0, res.get(key) - value));
}
return res;
}
// Returns the sum of the values in `count`.
private int sumValues(Map<Integer, Integer> count) {
return count.values().stream().mapToInt(Integer::intValue).sum();
}
}
// Accepted solution for LeetCode #3348: Smallest Divisible Digit Product II
func smallestNumber(num string, t int64) string {
primeCount, isDivisible := getPrimeCount(t)
if !isDivisible {
return "-1"
}
factorCount := getFactorCount(primeCount)
if sumValues(factorCount) > len(num) {
return construct(factorCount)
}
primeCountPrefix := getPrimeCountFromString(num)
firstZeroIndex := strings.Index(num, "0")
if firstZeroIndex == -1 {
firstZeroIndex = len(num)
if isSubset(primeCount, primeCountPrefix) {
return num
}
}
for i := len(num) - 1; i >= 0; i-- {
d := int(num[i] - '0')
primeCountPrefix = subtract(primeCountPrefix, kFactorCounts[d])
spaceAfterThisDigit := len(num) - 1 - i
if i > firstZeroIndex {
continue
}
for biggerDigit := d + 1; biggerDigit < 10; biggerDigit++ {
factorsAfterReplacement := getFactorCount(
subtract(subtract(primeCount, primeCountPrefix), kFactorCounts[biggerDigit]),
)
if sumValues(factorsAfterReplacement) <= spaceAfterThisDigit {
fillOnes := spaceAfterThisDigit - sumValues(factorsAfterReplacement)
return num[:i] + strconv.Itoa(biggerDigit) + strings.Repeat("1", fillOnes) + construct(factorsAfterReplacement)
}
}
}
factorsAfterExtension := getFactorCount(primeCount)
return strings.Repeat("1", len(num)+1-sumValues(factorsAfterExtension)) + construct(factorsAfterExtension)
}
var kFactorCounts = map[int]map[int]int{
0: {}, 1: {}, 2: {2: 1}, 3: {3: 1}, 4: {2: 2},
5: {5: 1}, 6: {2: 1, 3: 1}, 7: {7: 1}, 8: {2: 3}, 9: {3: 2},
}
func getPrimeCount(t int64) (map[int]int, bool) {
count := map[int]int{2: 0, 3: 0, 5: 0, 7: 0}
for _, prime := range []int{2, 3, 5, 7} {
for t%int64(prime) == 0 {
t /= int64(prime)
count[prime]++
}
}
return count, t == 1
}
func getPrimeCountFromString(num string) map[int]int {
count := map[int]int{2: 0, 3: 0, 5: 0, 7: 0}
for _, d := range num {
for prime, freq := range kFactorCounts[int(d-'0')] {
count[prime] += freq
}
}
return count
}
func getFactorCount(count map[int]int) map[int]int {
res := map[int]int{}
count8 := count[2] / 3
remaining2 := count[2] % 3
count9 := count[3] / 2
count3 := count[3] % 2
count4 := remaining2 / 2
count2 := remaining2 % 2
count6 := 0
if count2 == 1 && count3 == 1 {
count2, count3 = 0, 0
count6 = 1
}
if count3 == 1 && count4 == 1 {
count2 = 1
count6 = 1
count3, count4 = 0, 0
}
res[2] = count2
res[3] = count3
res[4] = count4
res[5] = count[5]
res[6] = count6
res[7] = count[7]
res[8] = count8
res[9] = count9
return res
}
func construct(factors map[int]int) string {
var res strings.Builder
for digit := 2; digit < 10; digit++ {
res.WriteString(strings.Repeat(strconv.Itoa(digit), factors[digit]))
}
return res.String()
}
func isSubset(a, b map[int]int) bool {
for key, value := range a {
if b[key] < value {
return false
}
}
return true
}
func subtract(a, b map[int]int) map[int]int {
res := make(map[int]int, len(a))
for k, v := range a {
res[k] = v
}
for k, v := range b {
res[k] = max(0, res[k]-v)
}
return res
}
func sumValues(count map[int]int) int {
sum := 0
for _, v := range count {
sum += v
}
return sum
}
# Accepted solution for LeetCode #3348: Smallest Divisible Digit Product II
FACTOR_COUNTS = {
0: collections.Counter(),
1: collections.Counter(),
2: collections.Counter([2]),
3: collections.Counter([3]),
4: collections.Counter([2, 2]),
5: collections.Counter([5]),
6: collections.Counter([2, 3]),
7: collections.Counter([7]),
8: collections.Counter([2, 2, 2]),
9: collections.Counter([3, 3]),
}
class Solution:
def smallestNumber(self, num: str, t: int) -> str:
primeCount, isDivisible = self._getPrimeCount(t)
if not isDivisible:
return '-1'
factorCount = self._getFactorCount(primeCount)
if sum(factorCount.values()) > len(num):
return ''.join(factor * freq for factor, freq in factorCount.items())
primeCountPrefix = sum((FACTOR_COUNTS[int(c)]
for c in num), start=collections.Counter())
firstZeroIndex = next((i for i, d in enumerate(num) if d == '0'), len(num))
if firstZeroIndex == len(num) and primeCount <= primeCountPrefix:
return num
for i, c in reversed(list(enumerate(num))):
d = int(c)
# Remove the current digit's factors from primeCountPrefix.
primeCountPrefix -= FACTOR_COUNTS[d]
spaceAfterThisDigit = len(num) - 1 - i
if i <= firstZeroIndex:
for biggerDigit in range(d + 1, 10):
# Compute the required factors after replacing with a larger digit.
factorsAfterReplacement = self._getFactorCount(
primeCount - primeCountPrefix - FACTOR_COUNTS[biggerDigit]
)
# Check if the replacement is possible within the available space.
if sum(factorsAfterReplacement.values()) <= spaceAfterThisDigit:
# Fill extra space with '1', if any, and construct the result.
fillOnes = spaceAfterThisDigit - sum(
factorsAfterReplacement.values())
return (
num[:i] # Keep the prefix unchanged.
+ str(biggerDigit) # Replace the current digit.
+ '1' * fillOnes # Fill remaining space with '1'.
+ ''.join(factor * freq for factor,
freq in factorsAfterReplacement.items())
)
# No solution of the same length exists, so we need to extend the number
# by prepending '1's and adding the required factors.
factorCount = self._getFactorCount(primeCount)
return (
'1' * (len(num) + 1 - sum(factorCount.values()))
+ ''.join(factor * freq for factor, freq in factorCount.items())
)
def _getPrimeCount(self, t: int) -> tuple[dict[int, int], bool]:
"""
Returns the count of prime factors of t and if t is divisible by 2, 3, 5, 7.
"""
count = collections.Counter()
for prime in [2, 3, 5, 7]:
while t % prime == 0:
t //= prime
count[prime] += 1
return count, t == 1
def _getFactorCount(self, count: dict[int, int]) -> dict[str, int]:
"""Returns the required factors to form the smallest number."""
count8, remaining2 = divmod(count[2], 3) # 2^3 = 8
count9, count3 = divmod(count[3], 2) # 3^2 = 9
count4, count2 = divmod(remaining2, 2) # 2^2 = 4
# Combine 2 and 3 to 6 if both are present.
count2, count3, count6 = ((0, 0, 1) if count2 == 1 and count3 == 1
else (count2, count3, 0))
# Combine 3 and 4 to 2 and 6 if both are present.
count2, count6, count3, count4 = ((1, 1, 0, 0)
if count3 == 1 and count4 == 1
else (count2, count6, count3, count4))
return {'2': count2, '3': count3, '4': count4, '5': count[5],
'6': count6, '7': count[7], '8': count8, '9': count9}
// Accepted solution for LeetCode #3348: Smallest Divisible Digit Product II
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3348: Smallest Divisible Digit Product II
// class Solution {
// public String smallestNumber(String num, long t) {
// Pair<Map<Integer, Integer>, Boolean> primeCountResult = getPrimeCount(t);
// Map<Integer, Integer> primeCount = primeCountResult.getKey();
// boolean isDivisible = primeCountResult.getValue();
// if (!isDivisible)
// return "-1";
//
// Map<Integer, Integer> factorCount = getFactorCount(primeCount);
// if (sumValues(factorCount) > num.length())
// return construct(factorCount);
//
// Map<Integer, Integer> primeCountPrefix = getPrimeCount(num);
// int firstZeroIndex = num.indexOf('0');
// if (firstZeroIndex == -1) {
// firstZeroIndex = num.length();
// if (isSubset(primeCount, primeCountPrefix))
// return num;
// }
//
// for (int i = num.length() - 1; i >= 0; --i) {
// final int d = num.charAt(i) - '0';
// // Remove the current digit's factors from primeCountPrefix.
// primeCountPrefix = subtract(primeCountPrefix, FACTOR_COUNTS.get(d));
// final int spaceAfterThisDigit = num.length() - 1 - i;
// if (i > firstZeroIndex)
// continue;
// for (int biggerDigit = d + 1; biggerDigit < 10; ++biggerDigit) {
// // Compute the required factors after replacing with a larger digit.
// Map<Integer, Integer> factorsAfterReplacement = getFactorCount(
// subtract(subtract(primeCount, primeCountPrefix), FACTOR_COUNTS.get(biggerDigit)));
// // Check if the replacement is possible within the available space.
// if (sumValues(factorsAfterReplacement) <= spaceAfterThisDigit) {
// // Fill extra space with '1', if any, and construct the result.
// final int fillOnes = spaceAfterThisDigit - sumValues(factorsAfterReplacement);
// return num.substring(0, i) + // Keep the prefix unchanged.
// biggerDigit + // Replace the current digit.
// "1".repeat(fillOnes) + // Fill remaining space with '1'.
// construct(factorsAfterReplacement);
// }
// }
// }
//
// // No solution of the same length exists, so we need to extend the number
// // by prepending '1's and adding the required factors.
// Map<Integer, Integer> factorsAfterExtension = getFactorCount(primeCount);
// return "1".repeat(num.length() + 1 - sumValues(factorsAfterExtension)) +
// construct(factorsAfterExtension);
// }
//
// private static final Map<Integer, Map<Integer, Integer>> FACTOR_COUNTS = Map.of(
// 0, Map.of(), 1, Map.of(), 2, Map.of(2, 1), 3, Map.of(3, 1), 4, Map.of(2, 2), 5, Map.of(5, 1),
// 6, Map.of(2, 1, 3, 1), 7, Map.of(7, 1), 8, Map.of(2, 3), 9, Map.of(3, 2));
//
// // Returns the prime count of t and if t is divisible by 2, 3, 5, 7.
// private Pair<Map<Integer, Integer>, Boolean> getPrimeCount(long t) {
// Map<Integer, Integer> count = new HashMap<>(Map.of(2, 0, 3, 0, 5, 0, 7, 0));
// for (int prime : new int[] {2, 3, 5, 7}) {
// while (t % prime == 0) {
// t /= prime;
// count.put(prime, count.get(prime) + 1);
// }
// }
// return new Pair<>(count, t == 1);
// }
//
// // Returns the prime count of `num`.
// private Map<Integer, Integer> getPrimeCount(String num) {
// Map<Integer, Integer> count = new HashMap<>(Map.of(2, 0, 3, 0, 5, 0, 7, 0));
// for (final char c : num.toCharArray()) {
// Map<Integer, Integer> digitFactors = FACTOR_COUNTS.get(c - '0');
// for (Map.Entry<Integer, Integer> entry : digitFactors.entrySet()) {
// final int prime = entry.getKey();
// final int freq = entry.getValue();
// count.merge(prime, freq, Integer::sum);
// }
// }
// return count;
// }
//
// private Map<Integer, Integer> getFactorCount(Map<Integer, Integer> count) {
// // 2^3 = 8
// final int count8 = count.get(2) / 3;
// final int remaining2 = count.get(2) % 3;
// // 3^2 = 9
// final int count9 = count.get(3) / 2;
// int count3 = count.get(3) % 2;
// // 2^2 = 4
// int count4 = remaining2 / 2;
// int count2 = remaining2 % 2;
// // Combine 2 and 3 to 6 if both are present
// int count6 = 0;
// if (count2 == 1 && count3 == 1) {
// count2 = 0;
// count3 = 0;
// count6 = 1;
// }
// // Combine 3 and 4 to 2 and 6 if both are present
// if (count3 == 1 && count4 == 1) {
// count2 = 1;
// count6 = 1;
// count3 = 0;
// count4 = 0;
// }
// return Map.of(2, count2, 3, count3, 4, count4, 5, count.get(5), 6, count6, 7, count.get(7), 8,
// count8, 9, count9);
// }
//
// private String construct(Map<Integer, Integer> factors) {
// StringBuilder sb = new StringBuilder();
// for (int digit = 2; digit < 10; ++digit)
// sb.append(String.valueOf(digit).repeat(factors.get(digit)));
// return sb.toString();
// }
//
// // Returns true if a is a subset of b.
// private boolean isSubset(Map<Integer, Integer> a, Map<Integer, Integer> b) {
// for (Map.Entry<Integer, Integer> entry : a.entrySet())
// if (b.get(entry.getKey()) < entry.getValue())
// return false;
// return true;
// }
//
// // Returns a - b.
// private Map<Integer, Integer> subtract(Map<Integer, Integer> a, Map<Integer, Integer> b) {
// Map<Integer, Integer> res = new HashMap<>(a);
// for (Map.Entry<Integer, Integer> entry : b.entrySet()) {
// final int key = entry.getKey();
// final int value = entry.getValue();
// res.put(key, Math.max(0, res.get(key) - value));
// }
// return res;
// }
//
// // Returns the sum of the values in `count`.
// private int sumValues(Map<Integer, Integer> count) {
// return count.values().stream().mapToInt(Integer::intValue).sum();
// }
// }
// Accepted solution for LeetCode #3348: Smallest Divisible Digit Product II
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #3348: Smallest Divisible Digit Product II
// class Solution {
// public String smallestNumber(String num, long t) {
// Pair<Map<Integer, Integer>, Boolean> primeCountResult = getPrimeCount(t);
// Map<Integer, Integer> primeCount = primeCountResult.getKey();
// boolean isDivisible = primeCountResult.getValue();
// if (!isDivisible)
// return "-1";
//
// Map<Integer, Integer> factorCount = getFactorCount(primeCount);
// if (sumValues(factorCount) > num.length())
// return construct(factorCount);
//
// Map<Integer, Integer> primeCountPrefix = getPrimeCount(num);
// int firstZeroIndex = num.indexOf('0');
// if (firstZeroIndex == -1) {
// firstZeroIndex = num.length();
// if (isSubset(primeCount, primeCountPrefix))
// return num;
// }
//
// for (int i = num.length() - 1; i >= 0; --i) {
// final int d = num.charAt(i) - '0';
// // Remove the current digit's factors from primeCountPrefix.
// primeCountPrefix = subtract(primeCountPrefix, FACTOR_COUNTS.get(d));
// final int spaceAfterThisDigit = num.length() - 1 - i;
// if (i > firstZeroIndex)
// continue;
// for (int biggerDigit = d + 1; biggerDigit < 10; ++biggerDigit) {
// // Compute the required factors after replacing with a larger digit.
// Map<Integer, Integer> factorsAfterReplacement = getFactorCount(
// subtract(subtract(primeCount, primeCountPrefix), FACTOR_COUNTS.get(biggerDigit)));
// // Check if the replacement is possible within the available space.
// if (sumValues(factorsAfterReplacement) <= spaceAfterThisDigit) {
// // Fill extra space with '1', if any, and construct the result.
// final int fillOnes = spaceAfterThisDigit - sumValues(factorsAfterReplacement);
// return num.substring(0, i) + // Keep the prefix unchanged.
// biggerDigit + // Replace the current digit.
// "1".repeat(fillOnes) + // Fill remaining space with '1'.
// construct(factorsAfterReplacement);
// }
// }
// }
//
// // No solution of the same length exists, so we need to extend the number
// // by prepending '1's and adding the required factors.
// Map<Integer, Integer> factorsAfterExtension = getFactorCount(primeCount);
// return "1".repeat(num.length() + 1 - sumValues(factorsAfterExtension)) +
// construct(factorsAfterExtension);
// }
//
// private static final Map<Integer, Map<Integer, Integer>> FACTOR_COUNTS = Map.of(
// 0, Map.of(), 1, Map.of(), 2, Map.of(2, 1), 3, Map.of(3, 1), 4, Map.of(2, 2), 5, Map.of(5, 1),
// 6, Map.of(2, 1, 3, 1), 7, Map.of(7, 1), 8, Map.of(2, 3), 9, Map.of(3, 2));
//
// // Returns the prime count of t and if t is divisible by 2, 3, 5, 7.
// private Pair<Map<Integer, Integer>, Boolean> getPrimeCount(long t) {
// Map<Integer, Integer> count = new HashMap<>(Map.of(2, 0, 3, 0, 5, 0, 7, 0));
// for (int prime : new int[] {2, 3, 5, 7}) {
// while (t % prime == 0) {
// t /= prime;
// count.put(prime, count.get(prime) + 1);
// }
// }
// return new Pair<>(count, t == 1);
// }
//
// // Returns the prime count of `num`.
// private Map<Integer, Integer> getPrimeCount(String num) {
// Map<Integer, Integer> count = new HashMap<>(Map.of(2, 0, 3, 0, 5, 0, 7, 0));
// for (final char c : num.toCharArray()) {
// Map<Integer, Integer> digitFactors = FACTOR_COUNTS.get(c - '0');
// for (Map.Entry<Integer, Integer> entry : digitFactors.entrySet()) {
// final int prime = entry.getKey();
// final int freq = entry.getValue();
// count.merge(prime, freq, Integer::sum);
// }
// }
// return count;
// }
//
// private Map<Integer, Integer> getFactorCount(Map<Integer, Integer> count) {
// // 2^3 = 8
// final int count8 = count.get(2) / 3;
// final int remaining2 = count.get(2) % 3;
// // 3^2 = 9
// final int count9 = count.get(3) / 2;
// int count3 = count.get(3) % 2;
// // 2^2 = 4
// int count4 = remaining2 / 2;
// int count2 = remaining2 % 2;
// // Combine 2 and 3 to 6 if both are present
// int count6 = 0;
// if (count2 == 1 && count3 == 1) {
// count2 = 0;
// count3 = 0;
// count6 = 1;
// }
// // Combine 3 and 4 to 2 and 6 if both are present
// if (count3 == 1 && count4 == 1) {
// count2 = 1;
// count6 = 1;
// count3 = 0;
// count4 = 0;
// }
// return Map.of(2, count2, 3, count3, 4, count4, 5, count.get(5), 6, count6, 7, count.get(7), 8,
// count8, 9, count9);
// }
//
// private String construct(Map<Integer, Integer> factors) {
// StringBuilder sb = new StringBuilder();
// for (int digit = 2; digit < 10; ++digit)
// sb.append(String.valueOf(digit).repeat(factors.get(digit)));
// return sb.toString();
// }
//
// // Returns true if a is a subset of b.
// private boolean isSubset(Map<Integer, Integer> a, Map<Integer, Integer> b) {
// for (Map.Entry<Integer, Integer> entry : a.entrySet())
// if (b.get(entry.getKey()) < entry.getValue())
// return false;
// return true;
// }
//
// // Returns a - b.
// private Map<Integer, Integer> subtract(Map<Integer, Integer> a, Map<Integer, Integer> b) {
// Map<Integer, Integer> res = new HashMap<>(a);
// for (Map.Entry<Integer, Integer> entry : b.entrySet()) {
// final int key = entry.getKey();
// final int value = entry.getValue();
// res.put(key, Math.max(0, res.get(key) - value));
// }
// return res;
// }
//
// // Returns the sum of the values in `count`.
// private int sumValues(Map<Integer, Integer> count) {
// return count.values().stream().mapToInt(Integer::intValue).sum();
// }
// }
Use this to step through a reusable interview workflow for this problem.
Generate every possible combination without any filtering. At each of n positions we choose from up to n options, giving nⁿ total candidates. Each candidate takes O(n) to validate. No pruning means we waste time on clearly invalid partial solutions.
Backtracking explores a decision tree, but prunes branches that violate constraints early. Worst case is still factorial or exponential, but pruning dramatically reduces the constant factor in practice. Space is the recursion depth (usually O(n) for n-level decisions).
Review these before coding to avoid predictable interview regressions.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Wrong move: Mutable state leaks between branches.
Usually fails on: Later branches inherit selections from earlier branches.
Fix: Always revert state changes immediately after recursive call.
Wrong move: Locally optimal choices may fail globally.
Usually fails on: Counterexamples appear on crafted input orderings.
Fix: Verify with exchange argument or monotonic objective before committing.