Question 17
Question 17
Letter Combinations of a Phone Number
Given a string containing digits from 2-9, return all possible letter combinations that the number could represent. Each digit corresponds to a set of letters on a traditional telephone keypad.
Approach: DFS
We can use Depth First Search (DFS) to explore all possible letter combinations by treating each digit as a level in a decision tree, where each branch corresponds to one of the letters mapped to that digit.
- Map Digits to Letters: Define a mapping from each digit to its corresponding letters.
- Recursive DFS: For each digit in the input, add each possible letter to a path and recursively explore the next digit. When the path reaches the same length as the input digits, add it to the result list.
- Backtracking: Use backtracking to remove the last letter after each recursive call to explore other branches.
Java Code Implementation
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PhoneNumberLetterCombinations {
// Map digits to corresponding letters
private static final Map<Character, String> phoneMap = new HashMap<>() {{
put('2', "abc"); put('3', "def");
put('4', "ghi"); put('5', "jkl"); put('6', "mno");
put('7', "pqrs"); put('8', "tuv"); put('9', "wxyz");
}};
// Method to return all letter combinations
public List<String> letterCombinations(String digits) {
List<String> combinations = new ArrayList<>();
// Edge case: empty input
if (digits == null || digits.isEmpty()) {
return combinations;
}
// Start DFS with an empty path
dfs(combinations, digits, new StringBuilder(), 0);
return combinations;
}
// DFS recursive function
private void dfs(List<String> combinations, String digits, StringBuilder path, int index) {
// Base case: path length matches digits length
if (index == digits.length()) {
combinations.add(path.toString());
return;
}
// Get the letters that the current digit maps to
char digit = digits.charAt(index);
String letters = phoneMap.get(digit);
// Recursive DFS on each letter
for (char letter : letters.toCharArray()) {
path.append(letter); // Choose letter
dfs(combinations, digits, path, index + 1); // Explore
path.deleteCharAt(path.length() - 1); // Backtrack
}
}
public static void main(String[] args) {
PhoneNumberLetterCombinations solution = new PhoneNumberLetterCombinations();
System.out.println(solution.letterCombinations("23")); // Example test case
}
}Explanation
DFS Recursive Function
The dfs function takes the current path and explores all possible branches (letters) mapped by the current digit. When index reaches digits.length(), the path is added to combinations as a complete combination.
Backtracking
After each recursive call, deleteCharAt() removes the last character from path, allowing the function to backtrack and explore other possible paths for previous digits.
Complexity Analysis
- Time Complexity: ( O(3^N \times 4^M) ), where ( N ) and ( M ) are the counts of digits that map to 3 letters (such as
2,3,4) and 4 letters (such as7,9) respectively. This reflects the total number of possible letter combinations. - Space Complexity: ( O(3^N \times 4^M) ), for storing the resulting list of combinations.
This complexity accounts for the recursive call stack and the storage required for all potential letter combinations.
