电话号码的字母组合

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

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

 

示例 1:

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

输入:digits = ""
输出:[]
示例 3:

输入:digits = "2"
输出:["a","b","c"]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 由于digits最多就四位,我们有一种最笨的方法就是直接四种情况都写出来:
 

def letterCombinations(digits: str):
    if not digits:
        return []
    dict = {
        "2": "abc",
        "3": "def",
        "4": "ghi",
        "5": "jkl",
        "6": "mno",
        "7": "pqrs",
        "8": "tuv",
        "9": "wxyz"
    }
    n = len(digits)
    li = set()
    if n == 1:
        return [x for x in dict[digits]]
    elif n == 2:
        for i in range(n):
            r = i + 1
            while r < n:
                for j in range(len(dict[digits[i]])):
                    for k in range(len(dict[digits[r]])):
                        li.add(dict[digits[i]][j] + dict[digits[r]][k])
                r += 1
    elif n == 3:
        li.clear()
        a = digits[0]
        b = digits[1]
        c = digits[2]
        for i in dict[a]:
            for j in dict[b]:
                for k in dict[c]:
                    li.add(i + j + k)
    else:
        li.clear()
        a = digits[0]
        b = digits[1]
        c = digits[2]
        d = digits[3]
        for i in dict[a]:
            for j in dict[b]:
                for k in dict[c]:
                    for z in dict[d]:
                        li.add(i + j + k + z)
    return list(li)

当然这个方法虽然行得通,但是太复杂(但我看别人有的用的这个方法运行的也挺快,可能是我写的复杂了)。但是肯定是有比这更好用的方法的,我们接着看。

def letterCombinations(self, digits: str) -> List[str]:
    if not digits:
        return []
    dict = {
        "2": "abc",
        "3": "def",
        "4": "ghi",
        "5": "jkl",
        "6": "mno",
        "7": "pqrs",
        "8": "tuv",
        "9": "wxyz"
    }
    s = []
    for i in digits:
        s.append(dict[i])
    result = []
    import itertools
    for i in itertools.product(*s):  # 在列表前加*号,会将列表拆分成一个一个的独立元素
        result.append(''.join(i))
    return result

这个方法使用了python中itertools库中的product方法,直接迭代出所有的排列组合。这个方法的速度就很快了。

执行结果:通过

执行用时:28 ms, 在所有 Python3 提交中击败了87.12%的用户

内存消耗:14.8 MB, 在所有 Python3 提交中击败了94.23%的用户

通过测试用例:25 / 25

最后一种方法是最官方的一种方法:回溯。

def letterCombinations(digits: str):
    if not digits:
        return list()

    phoneMap = {
        "2": "abc",
        "3": "def",
        "4": "ghi",
        "5": "jkl",
        "6": "mno",
        "7": "pqrs",
        "8": "tuv",
        "9": "wxyz",
    }

    def backtrack(index: int):
        if index == len(digits):
            combinations.append("".join(combination))
        else:
            digit = digits[index]
            for letter in phoneMap[digit]:
                combination.append(letter)
                backtrack(index + 1)
                combination.pop()

    combination = list()
    combinations = list()
    backtrack(0)
    return combinations

 我们首先得知道什么是回溯法:回溯法又称试探法。 回溯法的基本做法是深度优先搜索,是一种组织得井井有条的、能避免不必要重复搜索的穷举式搜索算法。 回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。

在本题我们先枚举digits,让后再枚举phoneMap中的字母。然后通过深度优先搜索,将所有的排列都穷举出来,大家可以debug亲自感受一下回溯法的精髓。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值