elements, method backtrack faces 1 + (โ !"# $%# โ &"!'# $ ๐) decision points, at each of which it repeatedly chooses a number that has not yet been used in the permutation currently being generated. Choosing a number is followed by a recursive call. The total number of calls is 1 + (โ!"# $ โ&"! $ ๐). def find_all_permutations(nums: List[Int]) -> List[List[Int]]: res = [] backtrack(nums, [], set(), res) return res def backtrack( nums: List[Int], candidate: List[Int], used: Set[Int], res: List[List[Int]] ) -> None: # If the current candidate is a complete # permutation, add it to the result. if len(candidate) == len(nums): res.append(candidate[:]) return for num in nums: if num not in used: # Add 'num' to the current permutation and mark it as used. candidate.append(num) used.add(num) # Recursively explore all branches using # the updated permutation candidate. backtrack(nums, candidate, used, res) # Backtrack by reversing the changes made. candidate.pop() used.remove(num) @alexxubyte Alex Xu @shaungunaw Shaun Gunawardane numbers to generate permutations with permutation grown so far numbers used up so far permutations generated so far This program is side-effecting, in that it adds/removes numbers to/from two mutable lists and a mutable set. The diagram below illustrates the computation of the permutations of a three-element list. E.g for a list with three elements: โข permutations = 3! = 3 x 2 x 1 = 6 โข decision pts = 1 + โ!"# (%# โ&"!'# ( ๐ = 10 โข calls = 1 + โ!"# ( โ&"! ( ๐ = 16 [] [4] [6] [4,5] [4,6] [4,5,6][4,6,5] choose 4 choose 6 choose 5 choose 6 choose 6 choose 5 [5] [5,4] [5,6] [5,4,6][5,6,4] choose 4 choose 6 choose 6 choose 4 [6,4] [6,5] [6,4,5][6,5,4] choose 4 choose 5 choose 5 choose 4 choose 5 nums candidate used [4,5,6] [] {} [4,5,6] [4] {4} [4,5,6] [4,5] {4,5} [4,5,6] [4,5,6] {4,5,6} [4,5,6] [4,6] {4,6} [4,5,6] [4,6,5] {4,6,5} [4,5,6] [5] {5} โฆ โฆ โฆ for num in [4,5,6]: if num not in {} for num in [4,5,6]: if num not in {4} for num in [4,5,6]: if num not in {4,5}