-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathpermutations.py
96 lines (85 loc) · 2.96 KB
/
permutations.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# 46. Permutations
# 🟠 Medium
#
# https://leetcode.com/problems/permutations/
#
# Tags: Array - Backtracking
import itertools
import timeit
from typing import List
# Use an array of digits to store the current permutation that we are
# building and an array of the same length as the input to mark which
# digits have been used already. Define a backtrack function that adds
# one more digit, out of the available ones to the sequence and calls
# itself. After the call we backtrack to leave the state ready for the
# next call.
#
# Time complexity: O(n!) - Where n is the number of digits in the input.
# Space complexity: O(n) - If we don't take into account the result
# array and only consider the sequences as we build them, the array of
# flags for the elements already used and the depth of the call stack.
# If we want to consider the size of the output array, then O(n!).
#
# Runtime: 65 ms, faster than 72.39%
# Memory Usage: 14.2 MB, less than 23.67%
class BackTrack:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
# Mark indexes that have been used.
used = [False] * len(nums)
# The digits of the current permutation.
digits = []
def bt() -> None:
# Base case, we have a full permutation.
if len(digits) == len(nums):
res.append(list(digits))
for i in range(len(nums)):
if not used[i]:
used[i] = True
digits.append(nums[i])
bt()
digits.pop()
used[i] = False
bt()
return res
# The itertools module provides a method that does exactly what the
# problem asks, we can use it directly.
#
# Runtime: 63 ms, faster than 72.39%
# Memory Usage: 13.9 MB, less than 84.81%
class Itertools:
def permute(self, nums: List[int]) -> List[List[int]]:
return list(map(list, itertools.permutations(nums)))
# On LeetCode it passes as
# return list(itertools.permutations(nums))
def test():
executors = [
BackTrack,
Itertools,
]
tests = [
# [[1], [[1]]],
# [[0, 1], [[0, 1], [1, 0]]],
[
[1, 2, 3],
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]],
],
]
for executor in executors:
start = timeit.default_timer()
for _ in range(1):
for n, t in enumerate(tests):
sol = executor()
result = sol.permute(t[0])
result.sort()
exp = t[1]
assert result == exp, (
f"\033[93m» {result} <> {exp}\033[91m for "
+ f"test {n} using \033[1m{executor.__name__}"
)
stop = timeit.default_timer()
used = str(round(stop - start, 5))
cols = "{0:20}{1:10}{2:10}"
res = cols.format(executor.__name__, used, "seconds")
print(f"\033[92m» {res}\033[0m")
test()