给定一个仅包含数字 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亲自感受一下回溯法的精髓。