回溯以获取电话号码的所有字母组合

时间:2019-02-08 00:20:51

标签: python backtracking

我目前正在为面试做练习。我正在研究的问题是获取电话号码的所有字母组合。

  

给出一个包含2到9(含2-9)数字的字符串,返回该数字可能代表的所有可能的字母组合。       下面给出了数字到字母的映射(就像在电话按钮上一样)。请注意,1不会映射到任何字母。

是问题所在,数字字母对的映射如下:

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

我对这个问题的解决方案如下:

def letterCombinations(self, digits):
    """
    :type digits: str
    :rtype: List[str]
    """

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

    def backtrack(digits, path, res):
        if digits == '':
            res.append(path)
            return
        for n in digits:
            for letter in letters[n]:
                path += letter
                backtrack(digits[1:], path, res)
                path = path[:-1]


    res = []
    backtrack(digits, '', res)
    return res

输入"23"的正确答案应该是["ad","ae","af","bd","be","bf","cd","ce","cf"],但是,我的答案看起来像

["ad","ae","af","bd","be","bf","cd","ce","cf","dd","de","df","ed","ee","ef","fd","fe","ff"]

获得所有所需的组合后,它会不断获得字母重叠的字母,例如dd de ee

我不知道为什么会这样,因为我只尝试浏览每个数字可能的字母并在此之后终止。

什么是导致此错误的原因?

4 个答案:

答案 0 :(得分:2)

我不了解您为什么这么做for n in digits:,每次回溯时,您都应该只关注当前数字(digits[0]),并仔细查看该数字的所有可能值,然后将其余工作传递给下一个递归调用。删除该行以及将n更改为digits[0]可以解决您的问题:

def letterCombinations(digits):
    """
    :type digits: str
    :rtype: List[str]
    """

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

    def backtrack(digits, path, res):
        if digits == '':
            res.append(path)
            return
        for letter in letters[digits[0]]:

            # note that you can replace this section with 
            # backtrack(digits[1:], path + letter, res)

            path += letter
            backtrack(digits[1:], path, res)
            path = path[:-1]


    res = []
    backtrack(digits, '', res)
    return res

letterCombinations('23')

输出:

['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']

此外,您还应该考虑使用itertools的@DYZ超简洁解决方案:

import itertools
letters = {'2':'abc', '3':'def','4':'ghi', '5':'jkl', '6':'mno', '7':'pqrs','8':'tuv', '9':'wxyz'}

def letterCombinations(digits):
    return ["".join(combo) for combo in itertools.product(*[letters[d] for d in digits])]

print(letterCombinations('23'))

输出:

['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']

答案 1 :(得分:1)

让我们从伪代码来看一下:

folds<-createFolds(file_test$y,k=10,list=TRUE)

这使我们的编程更短:

if digits is empty
    path is a solution
else
    for each letter in current digit
        stick the letter on the front of
           the letter combos for the rest of the input

答案 2 :(得分:0)

In [34]: def get_prod(number_list):
...:     let_list = [nums[i] for i in number_list]
...:     r = [[]]
...:     for p in let_list:
...:         r = [x + [y] for x in r for y in p]
...:     return [''.join(i) for i in r]
...:
...:

In [35]: get_prod(['2', '3', '4'])
Out[35]:
['adg',
 'adh',
 'adi',
 'aeg', ...

答案 3 :(得分:0)

如果您想知道为什么代码不起作用,那是因为您在函数调用中包含了最后一位数字。这导致它无法与最终数字配对。要解决此问题,您只需要在除最低级别之外的所有级别的数字上减少一个时间,如下所示:

def a(digits):
    """
    :type digits: str
    :rtype: List[str]
    """

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

    def backtrack(digits, path, res):
        if digits == '':
            res.append(path)
            return
        if len(digits) == 1:
            for letter in letters[digits[0]]:
                path += letter
                backtrack(digits[1:], path, res)
                path = path[:-1]
        else:
            for n in range(len(digits)-1):
                for letter in letters[digits[n]]:
                    path += letter
                    backtrack(digits[1:], path, res)
                    path = path[:-1]

    res = []
    backtrack(digits, '', res)
    return res