递归仅生成一对。我究竟做错了什么?

时间:2019-04-17 19:03:06

标签: python python-3.x recursion backtracking

我正在尝试从输入列表中创建排列。我的递归失败,并且只将我带回一个列表,该列表应该有多个。 我不确定自己的逻辑有什么问题-递归的新手。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        answer, perm = [], []
        self.dfs(nums, answer, perm)
        return answer

    def dfs(self, nums, answer, perm):
        if not nums:
            answer.append(perm)

        for ind, ele in enumerate(nums):
            perm.append(ele)
            nums.pop(ind)
            self.dfs(nums,answer, perm)

预期:[[1,2,3],[2,1,3],[2,3,1],[1,3,2],[3,1,2],[3,2 ,1]] 实际:[[1,2,3]]

3 个答案:

答案 0 :(得分:0)

您的代码的问题在于,在nums循环的每次迭代中,它都会从for中删除一个元素,并在nums被清空后返回答案。因此,使用输入[1,2,3],首先将1附加到perm上,然后从nums中删除,然后对2然后3进行相同操作,并且num为空后,将perm = [1,2,3]附加到ans并返回。

请注意,您可以简单地使用permutations()中的itertools方法从列表中生成排列:

import itertools

input_list = [1,2,3]
permutations = list(itertools.permutations(input_list))
print(permutations)

输出:

[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

答案 1 :(得分:0)

鉴于您的代码遵循来自编码挑战的代码问题的格式,我假设您想知道为什么您的解决方案不起作用,而不是使用内置于python的功能的其他解决方案。

您可以分两行进行参考:

import itertools
result = list(itertools.permutations([1, 2, 3]))
print(result)

使用list时出现的问题是它们都通过指针传递。这是一个递归解决方案。我添加了一些打印件,以便于查看正在发生的事情。

class Solution:
    def permutation(self, s):
        # if our list is only one element
        # then nest our list and return it
        if len(s) == 1:
            return [s]

        perm_list = [] # resulting list
        for element in s:
            # Grab elements other then the one we currently have
            remaining_elements = [x for x in s if x != element]

            # Permute on the remain elements
            # a list is returned
            print("Calling with", remaining_elements)
            permutations = self.permutation(remaining_elements) # permutations of sublist

            for perm in permutations:
                # combine our current element with the permuation
                perm_list.append([element] + perm) 
        print("Returning ", perm_list)
        return perm_list

答案 2 :(得分:0)

注销通过解决方案传递的一些数据会很有帮助,这样您就可以准确地看到自己在做什么错。如果我们在代码的每个步骤中分别记录numsperm,则会得到以下信息:

[1, 2, 3]             # nums 0
[]                    # perm 0
[2, 3]                # nums 1
[1]                   # perm 1
[3]                   # nums 2
[1, 2]                # perm 2
[]                    # nums 3
[[1, 2, 3]]           # result

您当前所有的代码都将元素从列表移动到包含原始列表的子列表。您需要跟踪哪些元素已添加到子列表中而不清空原始列表,然后可以创建所需的排列。您仍然可以通过递归来完成此操作,但是添加set的功能将使您的生活更加轻松。

这是一个基本示例,您可以根据需要进行调整:

def dfs(data, perm_out=None):
    if not perm_out:
        perm_out = []
    if not data:
        return [perm_out]
    res = []
    for point in data:
        u = {point}
        diff = data - u
        res += dfs(diff, perm_out + [point])
    return res

在您的简单输入数据上调用它:

i = [1, 2, 3]
u = dfs(set(i))
print(u)

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]