0

I was writing the following program to generate all possible permutations from a given list.

def permute(self, nums: List[int]) -> List[List[int]]:

        def __permute(nums, n, chosen, perms):
            if len(perms) == n:
                print(perms)
            else:
                for i in range(n):
                    if chosen[i]:
                        continue
                    else:
                        chosen[i] = True
                        perms.append(nums[i])
                        __permute(nums, n, chosen, perms)
                        perms.pop()
                        chosen[i] = False
            
        n = len(nums)
        __permute(nums, n, [False]*n, [])

For example:

Input: [1,2,3]
Output:
  [1,2,3]
  [1,3,2]
  [2,1,3]
  [2,3,1]
  [3,1,2]
  [3,2,1]

Now this time, I want to add all permutations in a list and return it:

Input: [1,2,3]
Output:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

Here is my code:

def permute(self, nums: List[int]) -> List[List[int]]:

        def __permute(nums, n, chosen, perms,res):
            if len(perms) == n:
                res.append(perms)
            else:
                for i in range(n):
                    if chosen[i]:
                        continue
                    else:
                        chosen[i] = True
                        perms.append(nums[i])
                        __permute(nums, n, chosen, perms, res)
                        perms.pop()
                        chosen[i] = False
            
        n = len(nums)
        res = []
        __permute(nums, n, [False]*n, [], res)
        return res

Problem is, the output is full of empty lists.

Input: [1,2,3]
Output:
[
  [],
  [],
  [],
  [],
  [],
  []
]

I fixed the bug by replacing res.append(perms) by res.append(perms[:]) but I don't understand why it works.

I also printed the id() of each perms and noticed something weird:

>>> print(id(perms))
>>>
140093677843328
140093677843328
140093677843328
140093677843328
140093677843328
140093677843328
>>> print(id(perms[:]))
>>>
140689610181440
140689610145600
140689610145600
140689610145600
140689610145600
140689610145600

Does anyone have an explanation to this behavior?

3
  • 1
    Because you are always working with the same perms list. And your algorithm clears that list, perms.pop()... so at the end, you end up with a bunch of refernces to the same empty list. Commented Jul 22, 2020 at 9:47
  • 1
    When res.append(perms), the list perms is given as a reference. This perms later becomes empty by perms.pop(). As a result, the returned values are all empty. Commented Jul 22, 2020 at 9:48
  • Ah! Got it now, thank you very much. Commented Jul 22, 2020 at 9:51

1 Answer 1

1

perms is the same object every time, but when you do perms[:] you are creating a copy of perms (which is a separate object from perms).

res (list) stores the reference to perms, so if change perms the same will be reflected on the list res.

But doing res[:] gives you a copy of perms (which is a different object) as mentioned above.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.