题目
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 digit 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'].
回溯解法
回溯 是一种通过探索所有潜在候选者来找到所有解决方案的算法。如果候选解决方案不是解决方案(或至少不是最后一个解决方案),则回溯算法会通过在上一步(即 回溯)上进行一些更改来丢弃它,然后再试一次。
这是一个回溯功能backtrack(combination, next_digits) ,它将正在进行的字母组合和接下来要检查的数字作为参数。
- 如果没有更多数字可检查,则表示当前组合已完成。
- 如果还有数字要检查:遍历映射下一个可用数字的字母。
将当前字母追加到当前组合combination = combination + letter
。
继续检查下一个数字:backtrack(combination + letter, next_digits[1:])
。
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
res = [] # 结果集
# 建立数字到字母的映射
dic = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs',
'8': 'tuv', '9': 'wxyz'}
# 如果输入为空,直接返回空结果
if len(digits) == 0:
return res
# 调用回溯函数开始查找所有可能的组合
self.backtrace(dic, digits, res, 0, '')
return res
def backtrace(self, dic, digits, res, i, temp):
# 如果当前的组合已经和输入的数字长度一致,说明找到了一个有效的组合,添加到结果集
if len(digits) == len(temp):
res.append(temp)
return
# 遍历当前数字对应的所有可能的字母
for letter in dic[digits[i]]:
# 递归调用回溯函数,寻找下一个数字对应的字母
self.backtrace(dic, digits, res, i+1, temp + letter)
复杂度分析:
时间复杂度:时间复杂度为O(4n),其中n为输入的数字串的长度。这是因为在最坏的情况下,一个数字可能映射到4个字母,每个字母都需要递归处理,所以时间复杂度为O(4n)。
空间复杂度:空间复杂度为O(n),其中n为输入的数字串的长度。这是因为在递归的过程中,需要额外的空间来存储临时的字符串,临时字符串的最大长度就是数字串的长度。另外,如果考虑结果集的空间,空间复杂度也为O(4^n)。
逐层往下解法
根据回溯的解法,当前层级的结果可以当做下个层级的输入,所以可以通过顺序的思维解法如下。这里需要注意,如果digits不为空,需要初始第一个值为空字符串""
.
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
res = [] # 结果集
# 建立数字到字母的映射
dic = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs',
'8': 'tuv', '9': 'wxyz'}
# 如果输入为空,直接返回空结果
if len(digits) == 0:
return res
pre_res = [] # 存储前一步的结果
res.append('') # 初始化结果集
# 遍历输入的每一个数字
for digit in digits:
pre_res, res = res, [] # 更新前一步的结果和当前结果
for i in dic[digit]: # 遍历当前数字对应的所有可能的字母
for s in pre_res: # 遍历前一步的所有结果
res.append(s+i) # 将当前字母添加到前一步的结果上,并保存到当前结果集
return res # 返回结果集
复杂度分析:
时间复杂度:时间复杂度为O(4n),其中n为输入的数字串的长度。这是因为在最坏的情况下,一个数字可能映射到4个字母,每个字母都需要处理,所以时间复杂度为O(4n)。
空间复杂度:空间复杂度为O(n),其中n为输入的数字串的长度。这是因为在迭代的过程中,需要额外的空间来存储临时的字符串,临时字符串的最大长度就是数字串的长度。另外,如果考虑结果集的空间,空间复杂度也为O(4^n)。