{x}
blog image

Letter Combinations of a Phone Number

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.

A mapping of digits to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

 

Example 1:

Input: digits = "23"
Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

Example 2:

Input: digits = ""
Output: []

Example 3:

Input: digits = "2"
Output: ["a","b","c"]

 

Constraints:

  • 0 <= digits.length <= 4
  • digits[i] is a digit in the range ['2', '9'].

Solution Explanation for Letter Combinations of a Phone Number

This problem asks to generate all possible letter combinations from a given digit string, where each digit maps to a set of letters as on a telephone keypad. We'll explore two common approaches: iterative traversal and recursive Depth-First Search (DFS).

Approach 1: Iterative Traversal

This approach builds the combinations iteratively. It starts with a list containing an empty string. In each iteration, it considers the letters corresponding to the current digit and extends each existing combination by appending each letter.

Algorithm:

  1. Initialization: Create a mapping d from digits ('2' to '9') to their corresponding letters. Initialize a list ans with an empty string.

  2. Iteration: Iterate through each digit in the input digits.

  3. Combination Extension: For each digit, retrieve its corresponding letters from d. Create a new list t. For every combination in ans, append each letter from the current digit's letters to the combination and add the new combination to t.

  4. Update ans: Replace ans with t.

  5. Return: After processing all digits, return ans.

Time Complexity: O(4n), where n is the length of digits. In the worst case, each digit maps to 4 letters, resulting in an exponential growth of combinations.

Space Complexity: O(4n) to store all possible combinations.

Approach 2: Depth-First Search (DFS)

DFS recursively explores all possible combinations. It builds combinations character by character, using backtracking to explore different letter choices at each digit.

Algorithm:

  1. Base Case: If all digits are processed, add the current combination to the result list.

  2. Recursive Step: For the current digit, iterate through its corresponding letters. Recursively call the function for the next digit, appending the current letter to the current combination. After the recursive call, backtrack by removing the added letter, ensuring that all letter combinations for the current digit are explored.

Time Complexity: O(4n), same as the iterative approach due to the exponential nature of the problem.

Space Complexity: O(n) for the recursive call stack, where n is the length of digits. The space used for storing the result is O(4n) but it's not considered in the recursive space complexity.

Code Examples (Python)

Approach 1 (Iterative):

def letterCombinations_iterative(digits: str) -> List[str]:
    if not digits:
        return []
    d = ["abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
    ans = [""]
    for digit in digits:
        new_ans = []
        for combo in ans:
            for letter in d[int(digit) - 2]:
                new_ans.append(combo + letter)
        ans = new_ans
    return ans
 

Approach 2 (DFS):

def letterCombinations_dfs(digits: str) -> List[str]:
    if not digits:
        return []
    d = ["abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
    ans = []
    
    def backtrack(index, combination):
        if index == len(digits):
            ans.append(combination)
            return
        digit = digits[index]
        letters = d[int(digit) - 2]
        for letter in letters:
            backtrack(index + 1, combination + letter)
    backtrack(0, "")
    return ans

Both approaches achieve the same result but differ in their implementation style and subtle aspects of space complexity. The iterative approach might be slightly more efficient in some cases due to avoiding function call overhead, but the DFS approach is often considered more readable and easier to understand for recursive problems. The choice depends on personal preference and coding style. The provided code examples show Python solutions, but the same logic can be applied to other programming languages.