🧠
Brute Force (Pure Recursion)
💡 Starting with brute force helps understand the problem deeply by exploring all possible letter combinations without optimization. It builds intuition for backtracking.
Intuition
At each digit, try every possible letter it maps to, then recursively do the same for the next digit until all digits are processed.
Algorithm
- Create a mapping from digits to letters.
- Define a recursive function that takes the current index and the current combination string.
- If the current index equals the length of digits, add the combination to results.
- Otherwise, for each letter mapped from the current digit, recurse with the next index and updated combination.
💡 The recursion builds combinations step-by-step, and the base case collects complete combinations.
def letterCombinations(digits):
if not digits:
return []
digit_map = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl',
'6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
result = []
def backtrack(index, path):
if index == len(digits):
result.append(path)
return
for char in digit_map[digits[index]]:
backtrack(index + 1, path + char)
backtrack(0, '')
return result
# Example usage:
if __name__ == '__main__':
print(letterCombinations('23'))
Line Notes
if not digits:Handle empty input early to avoid unnecessary processing and return empty list
digit_map = {...}Map digits to their corresponding letters as per phone keypad to know possible letters
result = []Initialize list to store all possible letter combinations
def backtrack(index, path):Define recursive helper to build combinations by exploring letters at each digit
if index == len(digits):Base case: all digits processed, add current combination to results
for char in digit_map[digits[index]]:Try each letter mapped from current digit to explore all branches
backtrack(index + 1, path + char)Recurse to next digit with updated combination string
import java.util.*;
public class Solution {
public List<String> letterCombinations(String digits) {
if (digits == null || digits.length() == 0) return new ArrayList<>();
String[] digitMap = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
List<String> result = new ArrayList<>();
backtrack(digits, 0, new StringBuilder(), digitMap, result);
return result;
}
private void backtrack(String digits, int index, StringBuilder path, String[] digitMap, List<String> result) {
if (index == digits.length()) {
result.add(path.toString());
return;
}
String letters = digitMap[digits.charAt(index) - '0'];
for (char c : letters.toCharArray()) {
path.append(c);
backtrack(digits, index + 1, path, digitMap, result);
path.deleteCharAt(path.length() - 1);
}
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.letterCombinations("23"));
}
}
Line Notes
if (digits == null || digits.length() == 0)Check for empty input to return early and avoid unnecessary processing
String[] digitMap = ...Array maps digit characters to their letters for quick lookup
List<String> result = new ArrayList<>();Initialize list to store all letter combinations
backtrack(digits, 0, new StringBuilder(), digitMap, result);Start recursion from first digit with empty path builder
if (index == digits.length())Base case: all digits processed, add current combination to results
String letters = digitMap[digits.charAt(index) - '0'];Get letters mapped from current digit
for (char c : letters.toCharArray())Iterate over letters mapped from current digit to explore all options
path.append(c);Add current letter to path before recursion
backtrack(digits, index + 1, path, digitMap, result);Recurse to next digit with updated path
path.deleteCharAt(path.length() - 1);Backtrack by removing last letter after recursion to explore other branches
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
vector<string> letterCombinations(string digits) {
if (digits.empty()) return {};
vector<string> digitMap = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
vector<string> result;
string path;
backtrack(digits, 0, path, digitMap, result);
return result;
}
private:
void backtrack(const string& digits, int index, string& path, const vector<string>& digitMap, vector<string>& result) {
if (index == digits.size()) {
result.push_back(path);
return;
}
string letters = digitMap[digits[index] - '0'];
for (char c : letters) {
path.push_back(c);
backtrack(digits, index + 1, path, digitMap, result);
path.pop_back();
}
}
};
int main() {
Solution sol;
vector<string> res = sol.letterCombinations("23");
for (auto& s : res) cout << s << " ";
cout << endl;
return 0;
}
Line Notes
if (digits.empty()) return {};Return empty vector immediately if input is empty to avoid processing
vector<string> digitMap = {...};Map digits to corresponding letters for quick lookup
vector<string> result;Initialize vector to store all letter combinations
string path;Mutable string to build current combination efficiently
void backtrack(...)Recursive helper function to build combinations by exploring letters at each digit
if (index == digits.size())Base case: all digits processed, add current path to results
string letters = digitMap[digits[index] - '0'];Get letters mapped from current digit
for (char c : letters)Try each letter mapped from current digit to explore all branches
path.push_back(c);Add letter to path before recursion
backtrack(digits, index + 1, path, digitMap, result);Recurse to next digit with updated path
path.pop_back();Backtrack by removing last letter after recursion to explore other branches
var letterCombinations = function(digits) {
if (!digits.length) return [];
const digitMap = {
'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl',
'6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'
};
const result = [];
function backtrack(index, path) {
if (index === digits.length) {
result.push(path);
return;
}
for (const char of digitMap[digits[index]]) {
backtrack(index + 1, path + char);
}
}
backtrack(0, '');
return result;
};
// Example usage:
console.log(letterCombinations('23'));
Line Notes
if (!digits.length) return [];Handle empty input by returning empty array early
const digitMap = {...};Object maps digits to their letters for quick lookup
const result = [];Initialize array to store all letter combinations
function backtrack(index, path)Recursive function to build combinations by exploring letters at each digit
if (index === digits.length)Base case: all digits processed, add current combination to results
for (const char of digitMap[digits[index]])Iterate over letters mapped from current digit to explore all options
backtrack(index + 1, path + char);Recurse to next digit with updated combination string
Each digit can map up to 4 letters (e.g., '7' or '9'), so total combinations are up to 4^n. Each combination is length n, so appending or creating strings takes O(n) time per combination. The recursion stack and path use O(n) space.
💡 For n=3 digits, this means up to 64 combinations, each length 3, so roughly 192 operations to build all strings. The recursion depth is n, so space is proportional to input length.
Interview Verdict: Accepted
Though brute force explores all combinations, it is efficient enough for typical input sizes and is a solid baseline solution.