*17. Letter Combinations of a Phone Number

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。

 

总结,对于这种递归类型也可以采用直接循环的方式,但是注意规律,即假设得到了当前的结果,那么下一次的结果如何得到?比如此题中的两两组合。

 

递归法?

posted @ 2019-04-10 15:40  三年一梦  阅读(183)  评论(0编辑  收藏  举报