LeetCode 热题 HOT 100 第九天 17. 电话号码的字母组合 中等题 用python3求解

题目地址

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述

示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]

示例 2:
输入:digits = “”
输出:[]

示例 3:
输入:digits = “2”
输出:[“a”,“b”,“c”]

提示:
0 <= digits.length <= 4
digits[i] 是范围 [‘2’, ‘9’] 的一个数字。

在这里插入图片描述

解法一:广度优先搜索的算法
利用队列,首先将第一个数字对应的字母放入到队列中,此时将字符串中的这个数字剔除,以此达到结束循环条件的目的,然后逐个弹出队列中的元素,与新的字母想对应,并压入到队列中,如果此时数字字符串空了,则队列中就是所有的字母组合。
例如:digits = 23
abc def
队列:a-b-c-ad-ae-af-bd-be-bf-cd-ce-cf

代码实现:

# 以下以digits = "23"为例
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits: #首先判断特殊情况,如果数字字符串为空
            return [] #返回空即可
        dic = {} #定义一个哈希表
        dic = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno',
                '7': 'pqrs', '8': 'tuv', '9': 'wxyz'} #将相应的数字与字母对应起来
        q = collections.deque() #首先初始化一个队列
        q.extend(dic[digits[0]]) #首先将数字字符串中的第一个数字对应的字母压入到队列中:print(q)为deque(['a', 'b', 'c'])
        digits = digits[1:] #将这个数字从字符串中移除,为了方便构建结束条件,此时赋值后digits[0]是指3
        while digits: #当数字字符串不为空时,此时表示还需要有新的字母组合
            for i in range(len(q)): #因为每个数字对应的字母均要用来进行字母组合,所以这边需要知道每一层的字母个数
                tmp = q.popleft() #首先将第一个元素弹出:tmp依次为a、b、c,首先从队列中弹出a,此时q为deque(['b', 'c'])
                print('tmp:',tmp)
                for j in range(len(dic[digits[0]])): #将第一个元素弹出,此时需要与第二个数字对应的字母进行组合,每个字母均需要,所以这边要按照长度进行遍历
                                                    #此时digits[0]是指3
                    tmp1 = tmp + dic[digits[0]][j] #将弹出的元素和新的字母进行组合
                    print('tmp1:',tmp1)
                    q.append(tmp1) #组合后放入队列中
                    print('q',q)
            digits = digits[1:] #将这个已经组合完成的数字移除
        res = [] #因为刚刚元素均存在了队列中,此时需要返回一个数组,所以需要重新初始化一个数组
        for p in range(len(q)): #将队列中的每一个元素弹出,并放入到结果数组中
            tmp_pop = q.popleft() #将队列中元素弹出
            print('tmp_pop',tmp_pop)
            res.append(tmp_pop) #放入结果数组中
            print('res',res)
        return res #返回结果即可

以23为例,print的过程:
tmp: a
tmp1: ad
q deque([‘b’, ‘c’, ‘ad’])
tmp1: ae
q deque([‘b’, ‘c’, ‘ad’, ‘ae’])
tmp1: af
q deque([‘b’, ‘c’, ‘ad’, ‘ae’, ‘af’])

tmp: b
tmp1: bd
q deque([‘c’, ‘ad’, ‘ae’, ‘af’, ‘bd’])
tmp1: be
q deque([‘c’, ‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’])
tmp1: bf
q deque([‘c’, ‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’])

tmp: c
tmp1: cd
q deque([‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’])
tmp1: ce
q deque([‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’, ‘ce’])
tmp1: cf
q deque([‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’, ‘ce’, ‘cf’])

tmp_pop ad
res [‘ad’]
tmp_pop ae
res [‘ad’, ‘ae’]
tmp_pop af
res [‘ad’, ‘ae’, ‘af’]
tmp_pop bd
res [‘ad’, ‘ae’, ‘af’, ‘bd’]
tmp_pop be
res [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’]
tmp_pop bf
res [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’]
tmp_pop cd
res [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’]
tmp_pop ce
res [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’, ‘ce’]
tmp_pop cf
res [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’, ‘ce’, ‘cf’]

为了方便看,无注释无print版本:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []
        dic = {}
        dic = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno',
                '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
        q = collections.deque() 
        q.extend(dic[digits[0]]) 
        digits = digits[1:] 
        while digits: 
            for i in range(len(q)): 
                tmp = q.popleft() 
                for j in range(len(dic[digits[0]])): 
                    tmp1 = tmp + dic[digits[0]][j] 
                    q.append(tmp1) 
            digits = digits[1:] 
        res = [] 
        for p in range(len(q)): 
            tmp_pop = q.popleft() 
            res.append(tmp_pop) 
        return res

解法二:深度优先搜索算法
深度优先搜索算法就是递归回溯了,递归三个需要提前确定的必要条件:输入参数、输出参数以及结束条件,结束条件就是字符串中遍历到最后一个数字对应的字母,也就是深度优先搜索算法,搜索到了最深的位置,所以结束条件就是index == n,输入参数是当前遍历到的数字字符串中的第几个数字index,返回参数就是最后的返回值,参考官方题解,写了下面的递归算法。
例如:digits = 235
abc def jkl
队列:a-ad-adj-ad-adk-ad-adl-ad-a-ae-aej-ae-aek-ae-ael-ae-a-af-afj-af-afk-af-afl-af-a-[]-b-bd-
bdj-bd-…

代码实现:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        dic = {'2':'abc', '3':'def', '4':'ghi', '5':'jkl', '6':'mno', '7':'pqrs','8':'tuv','9':'wxyz'} #首先定义一个哈希表,把相应的数字和字母对应起来
        n = len(digits) #计算给定字符串中数字的长度
        if n == 0:
            return []
        res = [] #初始化返回结果数组
        tmp = [] #初始化过渡数组

        def dfs(index): #定义递归回溯函数
            if index == n: #如果此时递归到了字符串中最后一个数字,则表示第一层深度搜索结束,将结果存储起来
                res.append(''.join(tmp)) #注意一下这边存储的时候要把多个字符串组合成一个字符串,利用
                #join函数,这边还要注意的是后面会把tmp中的最上面字符弹出,这边利用join函数也同时避免
                #了tmp弹出时影响res的目的,不然全部返回空字符串
                print('res:',res)
            else: #如果这个时候没搜索到最后一层,则
                for i in dic[digits[index]]: #逐个遍历当前数字对应的字母
                    tmp.append(i) #将这个字母加到tmp中
                    print('tmp1:',tmp)
                    dfs(index + 1) #因为要把下一个数字对应的字母继续加进去,所以这边index + 1,函数传递下一个位置
                    tmp.pop() #因为还需要把最后一个数字的字母逐个加进去,所以这边要把最后一个弹出,pop是出栈,后进先出,所以把d弹出去,tmp里值剩下a
                    #因为上一行的dfs函数遇到结束条件,才回向下执行,所以这边已经完成一次深度的搜索,此时要把最后一个字母弹出,实现下一轮遍历
                    print('tmp2:',tmp)
        dfs(0) #首先执行index = 0,因为都是从第一个字母开始组合    
        return res #返回结果函数

以23为例,print的过程:
tmp1: [‘a’]
tmp1: [‘a’, ‘d’]
res: [‘ad’]
tmp2: [‘a’]
tmp1: [‘a’, ‘e’]
res: [‘ad’, ‘ae’]
tmp2: [‘a’]
tmp1: [‘a’, ‘f’]
res: [‘ad’, ‘ae’, ‘af’]
tmp2: [‘a’]
tmp2: []
tmp1: [‘b’]
tmp1: [‘b’, ‘d’]
res: [‘ad’, ‘ae’, ‘af’, ‘bd’]
tmp2: [‘b’]
tmp1: [‘b’, ‘e’]
res: [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’]
tmp2: [‘b’]
tmp1: [‘b’, ‘f’]
res: [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’]
tmp2: [‘b’]
tmp2: []
tmp1: [‘c’]
tmp1: [‘c’, ‘d’]
res: [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’]
tmp2: [‘c’]
tmp1: [‘c’, ‘e’]
res: [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’, ‘ce’]
tmp2: [‘c’]
tmp1: [‘c’, ‘f’]
res: [‘ad’, ‘ae’, ‘af’, ‘bd’, ‘be’, ‘bf’, ‘cd’, ‘ce’, ‘cf’]
tmp2: [‘c’]
tmp2: []

为了方便看,无注释无print版本:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        dic = {'2':'abc', '3':'def', '4':'ghi', '5':'jkl', '6':'mno', '7':'pqrs','8':'tuv','9':'wxyz'} 
        n = len(digits) 
        if n == 0:
            return []
        res = [] 
        tmp = [] 

        def dfs(index): 
            if index == n: 
                res.append(''.join(tmp)) 
                print('res:',res)
            else: 
                for i in dic[digits[index]]: 
                    tmp.append(i) 
                    dfs(index + 1) 
                    tmp.pop() 
        dfs(0)
        return res 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值