Intuition
Each digit contributes one letter to the combination. Recurse position by position: for the current digit, try each of its letters, append it, recurse to the next digit, then undo. When all digits are placed, the built string is one combination.
Explanation
Idea
A combination picks exactly one letter per digit. This is a tree of choices: at depth i we choose a letter for digits[i], then move to depth i+1. Backtracking walks this tree, so every root-to-leaf path is one valid combination.
Algorithm
- Map each digit to its letters. If
digitsis empty, return[]. backtrack(index, path):- If
index == len(digits), recordpath. - Otherwise, for each letter of
digits[index], append it, recurse withindex+1, then pop.
- If
Worked example: "23"
- Digit
2→a/b/c; digit3→d/e/f. - Combinations:
ad, ae, af, bd, be, bf, cd, ce, cf.
Complexity
- Time: O(4^n · n) — up to 4 letters per digit, n digits.
- Space: O(n) recursion depth (plus output).
Implementation
import java.util.ArrayList;
import java.util.List;
class Solution {
private static final String[] MAP = {
"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"
};
public List<String> letterCombinations(String digits) {
List<String> result = new ArrayList<>();
if (digits.isEmpty()) {
return result;
}
backtrack(digits, 0, new StringBuilder(), result);
return result;
}
private void backtrack(String digits, int index, StringBuilder path, List<String> result) {
if (index == digits.length()) {
result.add(path.toString());
return;
}
String letters = MAP[digits.charAt(index) - '0'];
for (int i = 0; i < letters.length(); i++) {
path.append(letters.charAt(i));
backtrack(digits, index + 1, path, result);
path.deleteCharAt(path.length() - 1);
}
}
}