Facebook Pixel

1449. Form Largest Integer With Digits That Add up to Target

Problem Description

You need to form the largest possible integer by "painting" digits, where each digit has an associated cost.

The problem gives you:

  • An array cost where cost[i] represents the cost to paint digit (i + 1)
    • For example, cost[0] is the cost to paint digit 1, cost[1] is the cost to paint digit 2, and so on up to digit 9
  • A target value representing the exact total cost you must spend

Your goal is to find the maximum integer you can create by selecting and arranging digits such that:

  1. The sum of costs for all selected digits equals exactly target
  2. The resulting number doesn't contain the digit 0 (only digits 1-9 are available)
  3. You want the largest possible integer value

The key insights for maximizing the integer value:

  • First, maximize the number of digits (more digits means a larger number)
  • Among numbers with the same digit count, prefer using larger digits (9 is better than 1)
  • Digits can be reused multiple times

For example, if cost = [4,3,2,5,6,7,2,5,5] and target = 9:

  • Digit 3 costs 2, and digit 7 costs 2
  • You could paint "777" (cost: 2+2+2 = 6) or "7777" (cost: 2+2+2+2 = 8) or "77777" (cost: 2+2+2+2+2 = 10)
  • But since target is 9, you could paint "7773" (cost: 2+2+2+3 = 9)

The solution uses dynamic programming where:

  • f[i][j] tracks the maximum number of digits achievable using digits 1 through i with exact cost j
  • g[i][j] helps reconstruct which digits were chosen by storing the previous state
  • The algorithm fills the DP table considering whether to use digit i or not at each step
  • Finally, it reconstructs the answer by backtracking through the states, preferring larger digits when possible

Return the result as a string since the number can be very large. If it's impossible to spend exactly target cost, return "0".

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To get the largest possible number, we need to think about what makes one number larger than another. A number with more digits is always larger than a number with fewer digits (e.g., 1000 > 999). So our first priority is maximizing the number of digits we can paint with our budget.

This leads us to a key observation: if we want the most digits for our money, we should look for the cheapest digit available. However, once we know how many digits we can afford, we want those digits to be as large as possible (preferring 9s over 1s).

This creates a two-phase optimization problem:

  1. First, find the maximum number of digits we can paint with exactly target cost
  2. Then, among all ways to paint that many digits, choose the combination that gives the largest number

The challenge is that we can't just greedily pick the cheapest digit repeatedly. We need to spend exactly target cost, not just stay under it. For example, if the cheapest digit costs 3 and our target is 10, we can't paint 3 digits (cost 9) because we'd have 1 unit left over that we can't spend.

This "exact change" constraint naturally suggests dynamic programming. We can build up solutions by asking: "If I have budget j, what's the maximum number of digits I can paint using digits 1 through i?"

For each digit i and budget j, we have two choices:

  • Don't use digit i at all: inherit the best solution from digits 1 through i-1
  • Use digit i: if we have enough budget (j >= cost[i-1]), we can paint digit i and then solve the subproblem with remaining budget j - cost[i-1]

The DP table f[i][j] stores the maximum number of digits achievable. We also need g[i][j] to track our decisions so we can reconstruct which digits to use.

Once we've filled the DP table and know the maximum number of digits possible, we reconstruct the answer by working backwards. At each step, we greedily choose to use the largest digit possible (starting from 9 and going down). This ensures that our final number has the largest possible value among all numbers with the maximum digit count.

The reconstruction process examines g[i][j] to determine whether digit i was used. If g[i][j] == j, it means we didn't use digit i at that state, so we move to i-1. Otherwise, we used digit i, add it to our answer, and move to the state with reduced budget g[i][j].

Learn more about Dynamic Programming patterns.

Solution Approach

The solution uses a 2D dynamic programming approach with state reconstruction. Let's walk through the implementation step by step:

DP Table Setup:

  • f[i][j] represents the maximum number of digits we can paint using digits 1 through i with exact cost j
  • Initialize f with -inf to mark impossible states
  • Set f[0][0] = 0 as base case (0 digits with 0 cost)
  • g[i][j] stores the previous budget state to help reconstruct the solution

Filling the DP Table:

for i, c in enumerate(cost, 1):  # i represents digit i (1-indexed)
    for j in range(target + 1):  # j represents current budget

For each digit i and budget j, we make a decision:

  1. Option 1: Don't use digit i

    • Inherit the solution from f[i-1][j]
    • Set g[i][j] = j (budget remains unchanged)
  2. Option 2: Use digit i

    • Only possible if j >= c (enough budget)
    • New digit count would be f[i][j-c] + 1
    • Set g[i][j] = j - c (remaining budget after using digit i)

The decision logic:

if j < c or f[i][j - c] + 1 < f[i - 1][j]:
    f[i][j] = f[i - 1][j]    # Don't use digit i
    g[i][j] = j
else:
    f[i][j] = f[i][j - c] + 1  # Use digit i
    g[i][j] = j - c

We choose Option 2 (use digit i) only if:

  • We have enough budget (j >= c)
  • AND using digit i gives us more total digits (f[i][j-c] + 1 >= f[i-1][j])

Checking Feasibility:

if f[9][target] < 0:
    return "0"

If f[9][target] is negative, it's impossible to spend exactly target cost.

Reconstructing the Answer: Starting from state (i=9, j=target), we work backwards to build the largest number:

ans = []
i, j = 9, target
while i:
    if j == g[i][j]:
        i -= 1  # Digit i wasn't used, move to i-1
    else:
        ans.append(str(i))  # Digit i was used
        j = g[i][j]  # Move to previous budget state

The reconstruction starts from digit 9 and works down. This ensures we use the largest digits possible for the maximum digit count. When j != g[i][j], it means we used digit i at this state, so we:

  1. Add digit i to our answer
  2. Update j to the previous budget state g[i][j]

The algorithm continues until i = 0, at which point we've reconstructed all the digits used.

Time Complexity: O(9 * target) for filling the DP table and O(max_digits) for reconstruction Space Complexity: O(9 * target) for the two 2D arrays

The key insight is that by processing digits from 1 to 9 and reconstructing from 9 to 1, we automatically get the largest possible number among all numbers with the maximum digit count.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example with cost = [2, 4, 6, 2, 4, 6, 4, 4, 4] and target = 6.

This means:

  • Digit 1 costs 2, Digit 2 costs 4, Digit 3 costs 6
  • Digit 4 costs 2, Digit 5 costs 4, Digit 6 costs 6
  • Digit 7 costs 4, Digit 8 costs 4, Digit 9 costs 4

Step 1: Initialize DP tables

  • f[i][j] tracks max digits using digits 1-i with cost j
  • f[0][0] = 0, all other entries start as -inf

Step 2: Fill DP table for key states

For digit 1 (cost=2):

  • At j=2: Can use digit 1 once, f[1][2] = 1
  • At j=4: Can use digit 1 twice, f[1][4] = 2
  • At j=6: Can use digit 1 three times, f[1][6] = 3

For digit 4 (cost=2):

  • At j=2: Can use digit 4 once, f[4][2] = 1
  • At j=4: Can use digit 4 twice, f[4][4] = 2
  • At j=6: Can use digit 4 three times, f[4][6] = 3

Since digits 1 and 4 have the same cost (2), they achieve the same max digit counts. But digit 4 is larger, so when we have a choice, we prefer it.

For digit 9 (cost=4):

  • At j=4: Can use digit 9 once, f[9][4] = 1
  • At j=6: Best option is still three digits (using cheaper digits), f[9][6] = 3

Step 3: Check feasibility f[9][6] = 3, which is positive, so a solution exists.

Step 4: Reconstruct the answer Starting from state (i=9, j=6):

  1. i=9, j=6: Check if we used digit 9

    • g[9][6] tells us whether we used digit 9 here
    • Since using digit 9 (cost 4) would leave us with j=2, and we can get 1 more digit with cost 2, total would be 2 digits
    • But not using digit 9 and using cheaper digits gives us 3 digits
    • So g[9][6] = 6 (didn't use digit 9)
    • Move to i=8, j=6
  2. Continue checking digits 8, 7, 6, 5 (all cost 4 or 6)

    • Similar logic: using them gives fewer than 3 digits
    • Keep moving down without using them
  3. i=4, j=6: Check if we used digit 4

    • Using digit 4 (cost 2) leaves j=4, where we can get 2 more digits
    • Total: 3 digits, same as not using it
    • But digit 4 is valuable! g[4][6] = 4 (we did use digit 4)
    • Add "4" to answer, move to i=4, j=4
  4. i=4, j=4: Check if we used digit 4 again

    • Using digit 4 leaves j=2, where we can get 1 more digit
    • Total: 2 digits. g[4][4] = 2 (we did use digit 4)
    • Add "4" to answer, move to i=4, j=2
  5. i=4, j=2: Check if we used digit 4 again

    • Using digit 4 leaves j=0, where we have 0 more digits
    • Total: 1 digit. g[4][2] = 0 (we did use digit 4)
    • Add "4" to answer, move to i=4, j=0
  6. j=0, so we're done

Final answer: "444"

This makes sense because:

  • We maximized the number of digits (3 digits)
  • Among all ways to get 3 digits with cost 6, we used the largest possible digits (all 4s instead of mixing with 1s)
  • The cost is exactly 2+2+2 = 6

Solution Implementation

1class Solution:
2    def largestNumber(self, cost: List[int], target: int) -> str:
3        # dp[i][j] = maximum count of digits we can use with digits 1..i and exact cost j
4        # Initialize with negative infinity to mark invalid states
5        dp = [[-float('inf')] * (target + 1) for _ in range(10)]
6        dp[0][0] = 0  # Base case: 0 digits with 0 cost is valid (0 digits used)
7      
8        # parent[i][j] = the cost from which we transitioned to reach state (i, j)
9        # Used for backtracking to construct the answer
10        parent = [[0] * (target + 1) for _ in range(10)]
11      
12        # Fill the DP table
13        for digit in range(1, 10):  # Digits 1-9 (index i corresponds to digit i)
14            digit_cost = cost[digit - 1]  # Cost of current digit
15          
16            for current_cost in range(target + 1):
17                # Option 1: Don't use current digit, inherit from previous digit
18                dont_use = dp[digit - 1][current_cost]
19              
20                # Option 2: Use current digit (if we have enough budget)
21                if current_cost >= digit_cost:
22                    use_digit = dp[digit][current_cost - digit_cost] + 1
23                else:
24                    use_digit = -float('inf')
25              
26                # Choose the option that gives more digits
27                if use_digit > dont_use:
28                    dp[digit][current_cost] = use_digit
29                    parent[digit][current_cost] = current_cost - digit_cost
30                else:
31                    dp[digit][current_cost] = dont_use
32                    parent[digit][current_cost] = current_cost
33      
34        # Check if it's possible to achieve the target cost
35        if dp[9][target] < 0:
36            return "0"
37      
38        # Backtrack to construct the largest number
39        result = []
40        current_digit, remaining_cost = 9, target
41      
42        while current_digit > 0:
43            if remaining_cost == parent[current_digit][remaining_cost]:
44                # Current digit was not used, move to previous digit
45                current_digit -= 1
46            else:
47                # Current digit was used, add it to result
48                result.append(str(current_digit))
49                remaining_cost = parent[current_digit][remaining_cost]
50      
51        return "".join(result)
52
1class Solution {
2    public String largestNumber(int[] cost, int target) {
3        // Use a large negative value to represent impossible states
4        final int NEGATIVE_INFINITY = 1 << 30;
5      
6        // dp[i][j] represents the maximum number of digits we can use
7        // when considering digits 1 to i with total cost j
8        int[][] dp = new int[10][target + 1];
9      
10        // backtrack[i][j] stores the previous cost state for reconstruction
11        // If backtrack[i][j] == j, we didn't use digit i
12        // Otherwise, we used digit i and the previous state was j - cost[i-1]
13        int[][] backtrack = new int[10][target + 1];
14      
15        // Initialize all dp values to negative infinity (impossible states)
16        for (int[] row : dp) {
17            Arrays.fill(row, -NEGATIVE_INFINITY);
18        }
19      
20        // Base case: 0 digits with 0 cost gives 0 length
21        dp[0][0] = 0;
22      
23        // Fill the dp table for each digit from 1 to 9
24        for (int digit = 1; digit <= 9; digit++) {
25            int digitCost = cost[digit - 1];
26          
27            for (int currentCost = 0; currentCost <= target; currentCost++) {
28                // Option 1: Don't use the current digit
29                int withoutCurrentDigit = dp[digit - 1][currentCost];
30              
31                // Option 2: Use the current digit (if we have enough cost)
32                int withCurrentDigit = -NEGATIVE_INFINITY;
33                if (currentCost >= digitCost) {
34                    withCurrentDigit = dp[digit][currentCost - digitCost] + 1;
35                }
36              
37                // Choose the option that gives more digits
38                if (withCurrentDigit > withoutCurrentDigit) {
39                    dp[digit][currentCost] = withCurrentDigit;
40                    backtrack[digit][currentCost] = currentCost - digitCost;
41                } else {
42                    dp[digit][currentCost] = withoutCurrentDigit;
43                    backtrack[digit][currentCost] = currentCost;
44                }
45            }
46        }
47      
48        // If we can't form any number with the exact target cost, return "0"
49        if (dp[9][target] < 0) {
50            return "0";
51        }
52      
53        // Reconstruct the largest number by backtracking from the largest digit
54        StringBuilder result = new StringBuilder();
55        int currentDigit = 9;
56        int remainingCost = target;
57      
58        while (currentDigit > 0) {
59            // If backtrack value equals current cost, we didn't use this digit
60            if (remainingCost == backtrack[currentDigit][remainingCost]) {
61                currentDigit--;
62            } else {
63                // We used this digit, append it to result
64                result.append(currentDigit);
65                remainingCost = backtrack[currentDigit][remainingCost];
66            }
67        }
68      
69        return result.toString();
70    }
71}
72
1class Solution {
2public:
3    string largestNumber(vector<int>& cost, int target) {
4        // Initialize constants and data structures
5        const int INF = 1 << 30;  // Large negative value to represent impossible states
6      
7        // dp[i][j] = maximum number of digits achievable using digits 1 to i with total cost j
8        vector<vector<int>> dp(10, vector<int>(target + 1, -INF));
9      
10        // parent[i][j] = the cost from which we transitioned to reach state (i, j)
11        // Used for backtracking to reconstruct the solution
12        vector<vector<int>> parent(10, vector<int>(target + 1));
13      
14        // Base case: 0 digits with 0 cost is achievable with 0 digits
15        dp[0][0] = 0;
16      
17        // Fill the DP table for each digit from 1 to 9
18        for (int digit = 1; digit <= 9; ++digit) {
19            int digitCost = cost[digit - 1];  // Cost of current digit (0-indexed in cost array)
20          
21            for (int currentTarget = 0; currentTarget <= target; ++currentTarget) {
22                // Option 1: Don't use the current digit - inherit from previous digit
23                int withoutCurrentDigit = dp[digit - 1][currentTarget];
24              
25                // Option 2: Use the current digit (if we have enough budget)
26                int withCurrentDigit = -INF;
27                if (currentTarget >= digitCost) {
28                    withCurrentDigit = dp[digit][currentTarget - digitCost] + 1;
29                }
30              
31                // Choose the option that gives more digits
32                if (withCurrentDigit > withoutCurrentDigit) {
33                    dp[digit][currentTarget] = withCurrentDigit;
34                    parent[digit][currentTarget] = currentTarget - digitCost;  // Mark transition
35                } else {
36                    dp[digit][currentTarget] = withoutCurrentDigit;
37                    parent[digit][currentTarget] = currentTarget;  // No transition (same cost)
38                }
39            }
40        }
41      
42        // Check if it's impossible to achieve the target cost
43        if (dp[9][target] < 0) {
44            return "0";
45        }
46      
47        // Reconstruct the solution by backtracking through parent array
48        string result;
49        int currentDigit = 9;
50        int remainingTarget = target;
51      
52        // Start from largest digit (9) and work backwards for maximum value
53        while (currentDigit > 0) {
54            // Check if we used the current digit
55            if (parent[currentDigit][remainingTarget] == remainingTarget) {
56                // Didn't use this digit, move to smaller digit
57                --currentDigit;
58            } else {
59                // Used this digit, add it to result
60                result += '0' + currentDigit;
61                remainingTarget = parent[currentDigit][remainingTarget];
62            }
63        }
64      
65        return result;
66    }
67};
68
1/**
2 * Finds the largest number that can be formed with given digit costs and target sum
3 * @param cost - Array where cost[i] is the cost of digit (i+1)
4 * @param target - The target sum we need to achieve
5 * @returns The largest number as a string, or "0" if impossible
6 */
7function largestNumber(cost: number[], target: number): string {
8    // Large negative value to represent impossible states
9    const NEGATIVE_INFINITY = 1 << 30;
10  
11    // dp[i][j] represents the maximum number of digits we can use
12    // when considering digits 1 to i with total cost j
13    const dp: number[][] = Array(10)
14        .fill(0)
15        .map(() => Array(target + 1).fill(-NEGATIVE_INFINITY));
16  
17    // backtrack[i][j] stores the previous cost state for reconstruction
18    // If backtrack[i][j] = j, we didn't use digit i
19    // Otherwise, we used digit i and moved from cost backtrack[i][j]
20    const backtrack: number[][] = Array(10)
21        .fill(0)
22        .map(() => Array(target + 1).fill(0));
23  
24    // Base case: 0 digits with 0 cost is valid (0 digits used)
25    dp[0][0] = 0;
26  
27    // Fill the DP table for each digit from 1 to 9
28    for (let digit = 1; digit <= 9; ++digit) {
29        const digitCost = cost[digit - 1];
30      
31        for (let currentCost = 0; currentCost <= target; ++currentCost) {
32            // Option 1: Don't use current digit - inherit from previous digit
33            // Option 2: Use current digit if we have enough budget
34          
35            if (currentCost < digitCost || dp[digit][currentCost - digitCost] + 1 < dp[digit - 1][currentCost]) {
36                // Either can't afford this digit or using it doesn't give more digits
37                dp[digit][currentCost] = dp[digit - 1][currentCost];
38                backtrack[digit][currentCost] = currentCost;
39            } else {
40                // Use this digit as it gives us more total digits
41                dp[digit][currentCost] = dp[digit][currentCost - digitCost] + 1;
42                backtrack[digit][currentCost] = currentCost - digitCost;
43            }
44        }
45    }
46  
47    // Check if it's possible to form any number with exact target cost
48    if (dp[9][target] < 0) {
49        return '0';
50    }
51  
52    // Reconstruct the largest number by backtracking
53    // Start from largest digit (9) to ensure maximum value
54    const result: number[] = [];
55    let currentDigit = 9;
56    let remainingCost = target;
57  
58    while (currentDigit > 0) {
59        if (backtrack[currentDigit][remainingCost] === remainingCost) {
60            // Didn't use this digit, try smaller digit
61            --currentDigit;
62        } else {
63            // Used this digit, add it to result
64            result.push(currentDigit);
65            remainingCost = backtrack[currentDigit][remainingCost];
66        }
67    }
68  
69    // Convert digit array to string
70    return result.join('');
71}
72

Time and Space Complexity

Time Complexity: O(n * target) where n is the length of the cost array (which is 9 in this problem since digits are 1-9).

The algorithm uses dynamic programming with two nested loops:

  • The outer loop iterates through each digit from 1 to 9 (i.e., through the cost array)
  • The inner loop iterates through all possible values from 0 to target
  • Each iteration performs constant time operations (comparisons and assignments)
  • The reconstruction phase (while loop at the end) runs in O(target) time in the worst case, as we can select at most target digits (when all costs are 1)

Therefore, the overall time complexity is O(9 * target) + O(target) = O(target).

Space Complexity: O(n * target) = O(target)

The algorithm uses:

  • Two 2D arrays f and g, each of size 10 × (target + 1), requiring O(10 * target) = O(target) space
  • An array ans to store the result digits, which in the worst case could have target elements (when minimum cost is 1), requiring O(target) space
  • A few constant variables i, j, and c

The total space complexity is O(target) + O(target) = O(target).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect DP Initialization - Using 0 Instead of Negative Infinity

The Pitfall: A common mistake is initializing the DP table with 0 instead of negative infinity:

# WRONG - This makes invalid states appear valid
dp = [[0] * (target + 1) for _ in range(10)]

This causes the algorithm to incorrectly consider impossible states as valid (having 0 digits), leading to wrong answers when backtracking.

Why This Happens: When we check dp[digit][current_cost - digit_cost] + 1, if this cell contains 0 (but should be impossible), we'd incorrectly think we can add 1 digit to a valid 0-digit solution.

The Fix: Always initialize with negative infinity except for the base case:

dp = [[-float('inf')] * (target + 1) for _ in range(10)]
dp[0][0] = 0  # Only valid base case

2. Allowing Digit Reuse in the Wrong DP Dimension

The Pitfall: Using dp[digit - 1][current_cost - digit_cost] instead of dp[digit][current_cost - digit_cost]:

# WRONG - Prevents digit reuse
use_digit = dp[digit - 1][current_cost - digit_cost] + 1

This would mean each digit can only be used once, drastically limiting our solutions.

The Fix: Allow the same digit to be reused by referencing the same digit row:

# CORRECT - Allows digit reuse
use_digit = dp[digit][current_cost - digit_cost] + 1

3. Incorrect Backtracking Logic

The Pitfall: During reconstruction, incorrectly determining when a digit was used:

# WRONG - Comparing with wrong value
if parent[current_digit][remaining_cost] != remaining_cost - cost[current_digit - 1]:
    current_digit -= 1
else:
    result.append(str(current_digit))
    remaining_cost = parent[current_digit][remaining_cost]

Why This Fails: The parent array stores the previous cost state, not the cost difference. Misunderstanding this leads to incorrect digit selection.

The Fix: Check if the cost remained the same (digit not used) or changed (digit used):

if remaining_cost == parent[current_digit][remaining_cost]:
    # Cost unchanged - digit not used
    current_digit -= 1
else:
    # Cost changed - digit was used
    result.append(str(current_digit))
    remaining_cost = parent[current_digit][remaining_cost]

4. Not Handling the Greedy Choice Correctly

The Pitfall: Breaking ties incorrectly when multiple options give the same digit count:

# WRONG - Using >= instead of >
if use_digit >= dont_use:  # This might not give largest number
    dp[digit][current_cost] = use_digit

Why This Matters: When use_digit == dont_use, we have two ways to achieve the same digit count. Since we process digits from 1 to 9 and reconstruct from 9 to 1, using >= would prefer smaller digits when counts are equal, giving a smaller final number.

The Fix: Use strict inequality to prefer the "don't use" option when counts are equal:

if use_digit > dont_use:  # Only use digit if it gives MORE digits
    dp[digit][current_cost] = use_digit

This ensures that during backtracking from digit 9 to 1, we naturally prefer larger digits when multiple options exist for the same digit count.

5. Off-by-One Errors with Digit Indexing

The Pitfall: Forgetting that digit i corresponds to cost[i-1]:

# WRONG - Using wrong index
digit_cost = cost[digit]  # Should be cost[digit - 1]

The Fix: Always remember the mapping: digit 1 → cost[0], digit 2 → cost[1], ..., digit 9 → cost[8]:

digit_cost = cost[digit - 1]
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What's the output of running the following function using input 56?

1KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12def letter_combinations_of_phone_number(digits):
13    def dfs(path, res):
14        if len(path) == len(digits):
15            res.append(''.join(path))
16            return
17
18        next_number = digits[len(path)]
19        for letter in KEYBOARD[next_number]:
20            path.append(letter)
21            dfs(path, res)
22            path.pop()
23
24    res = []
25    dfs([], res)
26    return res
27
1private static final Map<Character, char[]> KEYBOARD = Map.of(
2    '2', "abc".toCharArray(),
3    '3', "def".toCharArray(),
4    '4', "ghi".toCharArray(),
5    '5', "jkl".toCharArray(),
6    '6', "mno".toCharArray(),
7    '7', "pqrs".toCharArray(),
8    '8', "tuv".toCharArray(),
9    '9', "wxyz".toCharArray()
10);
11
12public static List<String> letterCombinationsOfPhoneNumber(String digits) {
13    List<String> res = new ArrayList<>();
14    dfs(new StringBuilder(), res, digits.toCharArray());
15    return res;
16}
17
18private static void dfs(StringBuilder path, List<String> res, char[] digits) {
19    if (path.length() == digits.length) {
20        res.add(path.toString());
21        return;
22    }
23    char next_digit = digits[path.length()];
24    for (char letter : KEYBOARD.get(next_digit)) {
25        path.append(letter);
26        dfs(path, res, digits);
27        path.deleteCharAt(path.length() - 1);
28    }
29}
30
1const KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12function letter_combinations_of_phone_number(digits) {
13    let res = [];
14    dfs(digits, [], res);
15    return res;
16}
17
18function dfs(digits, path, res) {
19    if (path.length === digits.length) {
20        res.push(path.join(''));
21        return;
22    }
23    let next_number = digits.charAt(path.length);
24    for (let letter of KEYBOARD[next_number]) {
25        path.push(letter);
26        dfs(digits, path, res);
27        path.pop();
28    }
29}
30

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More