1. 原始题目
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23" 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
2. 解法
这题明显可以用递归。但是不太好理解,参考了Leetcode上的一个解法,还是很主直观的,分析如下:
先上代码:
class Solution: def letterCombinations(self, digits: str) -> List[str]: if '' == digits: return [] # 空则返 kvmaps = { '2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz' } ret=[''] # 用来存放上一次的结果,即添加当前数字前的结果 for c in digits: # 对于字符串里每个数字而言 tmp=[] # 临时空间 for y in ret: # 对于上次的结果 for x in kvmaps[c]: # 对于上次的结果,每再添加一个数,都要两两组合 tmp.append(y+x) # 记录两两组合的结果 ret=tmp # 当前新的结果,即加入数字c后的结果 return ret
思路和代码分析:
例如数字234:我们分三次读取即2 3 4
1)首先读入2:
2里面有abc三个,而上次没有结果,因为2是第一个数,没有上次,所以上次即记为空,及代码最开始的ret=[' ']。所以如果仅仅是2的话,那我们只能返回这次结果ret=[a b c]了。
2)接着读入3:
3里面有def三个,上次的结果为ret=[a b c],所以需要d e f与上次的结果ret两两组合:[ad ae af bd be bf cd ce cf]。这次的新结果依然存在ret里。
这时会发现一个规律,每次新添加一个数字时,就将上次ret里的字母和他这个新数字的所有字母取值两两组合即可。
3)最后读入4:
4里面有ghi三个,上次的结果在ret里,所以需要ret里面的元素和ghi再两两组合得到新的结果,存在ret里,即为更新ret,所以最后返回ret。
总结,对于这种递归类型也可以采用直接循环的方式,但是注意规律,即假设得到了当前的结果,那么下一次的结果如何得到?比如此题中的两两组合。
递归法?