Python面试宝典第33题:电话号码的字母组合

题目

给定一个仅包含数字2-9的字符串,返回所有它能表示的字母组合,答案可以按任意顺序返回。给出数字到字母的映射如下图(与手机按键相同)。注意:1不对应任何字母。

示例 1:

python 复制代码
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

python 复制代码
输入:digits = ""
输出:[]

示例 3:

python 复制代码
输入:digits = "2"
输出:["a","b","c"]

递归法

使用递归法求解本题的基本思想是:建立数字到字母的映射关系(比如:数字2对应字母"abc");对于给定的数字串,从左到右逐个数字考虑,针对每个数字生成对应的字母,并与之前已有的组合进行连接形成新的组合。使用递归法求解本题的主要步骤如下。

1、创建一个字典phone,用于存储数字到字母的映射。

2、定义一个递归函数backtrack,它接受当前组合combination和剩余未处理的数字串next_digits作为参数。

3、如果next_digits为空,说明当前组合已完成,将其加入结果列表。

4、否则,取出next_digits的第一个数字,并获取该数字对应的字母,然后对这些字母进行循环,将每个字母添加到combination的末尾,并递归地处理剩余的数字。

5、在递归返回后,从combination中移除最后添加的字母,以便于下一次迭代可以尝试其他字母。

根据上面的算法步骤,我们可以得出下面的示例代码。

python 复制代码
def letter_combinations_by_recursion(digits):
    # 定义数字到字母的映射
    phone = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', 
             '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
    result = []

    # 递归函数
    def backtrack(combination, next_digits):
        # 如果没有剩余的数字
        if len(next_digits) == 0:
            result.append(combination)
        else:
            # 获取下一个数字对应的字母
            for letter in phone[next_digits[0]]:
                # 递归调用
                backtrack(combination + letter, next_digits[1:])

    if not digits:
        return []

    backtrack("", digits)
    return result
    
print(letter_combinations_by_recursion("23"))
print(letter_combinations_by_recursion(""))
print(letter_combinations_by_recursion("2"))

迭代法

使用迭代法求解本题的基本思想是:利用栈(stack)或队列(queue)来模拟递归过程中的状态转移。解题的主要步骤如下。

1、初始化。创建一个队列queue,并将初始的空字符串加入队列。同时,创建一个字典phone,用于存储数字到字母的映射。

2、迭代处理。从输入的数字串的第一个数字开始,每次取出队列中的元素,并将当前数字对应的字母逐一添加到这些元素后面,形成新的组合,最后将这些新组合加入队列。

3、终止条件。当所有数字都已经被处理过,队列中的元素即为最终的结果。

根据上面的算法步骤,我们可以得出下面的示例代码。

python 复制代码
from collections import deque

def letter_combinations_by_iteration(digits):
    # 定义数字到字母的映射
    phone = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', 
             '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
    result = []

    # 如果输入的字符串为空,直接返回空列表
    if not digits:
        return result

    # 创建一个队列,并将初始的空字符串加入队列
    queue = deque([''])

    # 遍历输入的数字串
    for digit in digits:
        # 队列的长度会随着迭代而变化,这里记录当前长度
        size = len(queue)
        # 处理当前数字对应的字母
        for _ in range(size):
            # 取出队列中的组合
            combination = queue.popleft()
            # 将当前数字对应的字母逐一添加到组合后面
            for letter in phone[digit]:
                # 形成新的组合并加入队列
                queue.append(combination + letter)

    while queue:
        result.append(queue.popleft())

    return result

print(letter_combinations_by_iteration("23"))
print(letter_combinations_by_iteration(""))
print(letter_combinations_by_iteration("2"))

总结

递归法求解本题时,每个数字对应最多4个字母,所以递归的深度是输入数字的长度,每层递归需要遍历该数字对应的字母数量。因此,时间复杂度是 O(4^n)。其中,n是输入数字的长度。递归调用栈的最大深度与输入数字的长度相同,因此空间复杂度为O(n)。

与递归法一样,迭代法的时间复杂度也是O(4^n)。迭代法使用队列存储了中间结果,空间复杂度为O(n * 4^n)。这是因为,在最坏情况下,队列可能需要存储所有可能的组合。

相关推荐
vx_BS8133014 分钟前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计
gzxx2007sddx20 分钟前
windows vnpy运行过程及问题记录
python·量化·vnpy
yyy(十一月限定版)27 分钟前
寒假集训4——二分排序
算法
星火开发设计27 分钟前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
蒹葭玉树38 分钟前
【C++上岸】C++常见面试题目--操作系统篇(第二十八期)
linux·c++·面试
醉颜凉38 分钟前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树
达文汐41 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗41 分钟前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子41 分钟前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
算法_小学生43 分钟前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode