Letter combinations
17. 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"]
Solutions
1. DFS way
MAPPING = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
n = len(digits)
if n == 0:
return []
ans = []
path = [''] * n
def dfs(i):
if i == n:
ans.append(''.join(path))
return
for c in MAPPING[int(digits[i])]:
path[i] = c
dfs(i+1)
dfs(0)
return ans
Input: 23
output:
['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']
This solution is pretty neat. We just iterate one digit after another recursive until we reach the end
2. Stack way
MAPPING = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
ans = []
if len(digits) == 0:
return []
q = [('',0)] # '' is the previous str, 0 is the length of the current select
while len(q) > 0:
ch,count = q.pop(0)
if count == len(digits):
ans.append(ch)
else:
letters = MAPPING[int(digits[count])]
for letter in letters:
q.append((ch + letter, count+1))
return ans
Input: 23
output:
['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']
Derivation
What if if we choose all least one element from number’s corresponding letters ? For example, we can choose 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc' from number 1. Then the available combinations will be???
If we want to gain all the available combinations of the given string. First we need to get all the combinations for a given letter. To achieve that, we can use the following function.
def list_powerset(lst):
result = [""]
for x in lst:
result.extend([subset + x for subset in result])
result.remove("")
return result
The list_powerset will take an array, for example abc. It will return all the possible combination except "", Since the question asked for we select at least one letter in the possible string array.
The powerset of abc is ['a', 'b', 'ab', 'c', 'ac', 'bc', 'abc']
After we get the possibility one specific number, we can modified the previous solution into the following:
MAPPING = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
def list_powerset(lst):
result = [""]
for x in lst:
result.extend([subset + x for subset in result])
result.remove("")
return result
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
ans = []
if len(digits) == 0:
return []
q = [('',0)]
while len(q) > 0:
ch,count = q.pop(0)
if count == len(digits):
ans.append(ch)
else:
letters = MAPPING[int(digits[count])]
for letter in list_powerset(letters):
q.append((ch + letter, count+1))
return ans
Input: 23
output:
['ad', 'ae', 'ade', 'af', 'adf', 'aef', 'adef', 'bd', 'be', 'bde', 'bf', 'bdf', 'bef', 'bdef', 'abd', 'abe', 'abde', 'abf', 'abdf', 'abef', 'abdef', 'cd', 'ce', 'cde', 'cf', 'cdf', 'cef', 'cdef', 'acd', 'ace', 'acde', 'acf', 'acdf', 'acef', 'acdef', 'bcd', 'bce', 'bcde', 'bcf', 'bcdf', 'bcef', 'bcdef', 'abcd', 'abce', 'abcde', 'abcf', 'abcdf', 'abcef', 'abcdef']
Comments