电话号码字母组合题目要求根据输入的数字字符串,返回所有可能的字母组合,每个数字对应手机键盘上的几个字母,比如2对应abc,3对应def。实现这个逻辑时,很多开发者会先构建数字到字母的映射字典,再使用回溯法遍历所有组合可能。

数字到字母的映射字典构建
首先我们需要构建数字和对应字母的映射关系,这里要注意避免字典键重复的陷阱。有些开发者可能会错误地使用列表或者重复赋值的方式构建字典,导致后面的键值覆盖前面的内容,比如下面的错误示例:
# 错误示例:字典键重复导致覆盖
phone_map = {}
phone_map["2"] = "abc"
phone_map["2"] = "def" # 这里会覆盖前面的abc,导致映射错误
print(phone_map["2"]) # 输出def,不符合预期
正确的映射构建方式应该是每个数字键只赋值一次,完整的正确映射如下:
# 正确的数字到字母映射字典
phone_map = {
"2": "abc",
"3": "def",
"4": "ghi",
"5": "jkl",
"6": "mno",
"7": "pqrs",
"8": "tuv",
"9": "wxyz"
}
回溯法的实现逻辑
回溯法的核心思路是逐步构建组合,每次处理一个数字对应的所有字母,递归处理下一个数字,直到处理完所有数字,将当前组合加入结果集。具体实现步骤如下:
- 初始化结果列表,用来存储所有符合要求的字母组合
- 定义递归函数,参数包含当前处理的数字索引、当前已经构建的字母组合
- 如果当前索引等于数字字符串的长度,说明已经处理完所有数字,将当前组合加入结果列表
- 否则获取当前数字对应的字母集合,遍历每个字母,将其加入当前组合,递归处理下一个数字索引
- 递归返回后撤销上一次添加的字母,继续遍历下一个字母
完整回溯法实现代码
结合正确的映射字典和回溯逻辑,完整的实现代码如下:
def letter_combinations(digits):
# 处理空输入的情况
if not digits:
return []
# 正确的数字到字母映射
phone_map = {
"2": "abc",
"3": "def",
"4": "ghi",
"5": "jkl",
"6": "mno",
"7": "pqrs",
"8": "tuv",
"9": "wxyz"
}
result = []
# 递归回溯函数
def backtrack(index, current):
# 终止条件:处理完所有数字
if index == len(digits):
result.append(current)
return
# 获取当前数字对应的字母
current_digit = digits[index]
letters = phone_map[current_digit]
# 遍历每个字母,递归处理
for letter in letters:
backtrack(index + 1, current + letter)
# 从第0个索引开始,初始组合为空
backtrack(0, "")
return result
# 测试代码
if __name__ == "__main__":
test_digits = "23"
print(f"输入数字{test_digits}的字母组合为:{letter_combinations(test_digits)}")
字典键重复陷阱的规避方法
除了构建字典时重复赋值的问题,还有一种常见的键重复陷阱是使用了可变类型作为字典键,或者误将不同数字映射到了同一个键上。规避这类问题的方法有:
- 构建映射字典时,一次性写完所有键值对,避免后续重复赋值覆盖
- 构建完成后可以打印字典内容,检查每个键对应的字母是否正确
- 如果数字映射有调整,直接修改对应键的value,不要新增重复的键
上面的完整代码中,映射字典在定义时就完成了所有键值对的初始化,不会出现键重复覆盖的问题,回溯逻辑也清晰处理了所有组合的遍历,能够准确返回符合要求的字母组合结果。