-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathpascals-triangle.py
105 lines (96 loc) · 3.23 KB
/
pascals-triangle.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
97
98
99
100
101
102
103
104
105
# 118. Pascal's Triangle
# 🟢 Easy
#
# https://leetcode.com/problems/pascals-triangle/
#
# Tags: Array - Dynamic Programming
import timeit
from typing import List
# Create the result matrix and then, starting at the third row, fill the
# values for each row based on the values found on the previous row.
#
# Time complexity: O(n^2) - We visit each element twice, when we create
# the empty matrix and when we calculate its value. The number of
# elements has a quadratic relation to the value of the input n and a
# linear O(n) relation to the output.
# Space complexity; O(n^2) - Same as above. Quadratic relation with the
# value of the input and linear with the size of the output.
#
# Runtime 50 ms Beats 43.34%
# Memory 13.9 MB Beats 66.48%
class CreateUpdate:
def generate(self, numRows: int) -> List[List[int]]:
# Create the result matrix prefilled with ones. This solves edge
# cases when numRows < 2.
matrix = [[1] * (x + 1) for x in range(numRows)]
# Starting at the 3rd row, fill in the values for all rows.
for row_idx in range(2, numRows):
# Generate row sums avoiding the first and last element.
for col_idx in range(1, row_idx):
# pos = top_left + top_right when center-aligned.
matrix[row_idx][col_idx] = (
matrix[row_idx - 1][col_idx - 1]
+ matrix[row_idx - 1][col_idx]
)
return matrix
# Similar idea, and O complexity, but slower because append needs to
# grow the matrix, using O(n) time, each time that it doubles in size.
# Between grow operations, append is O(1).
#
# Runtime 63 ms Beats 12.86%
# Memory 14 MB Beats 17.88%
class Append:
def generate(self, numRows: int) -> List[List[int]]:
if numRows == 1:
return [[1]]
matrix = [[1], [1, 1]]
if numRows == 2:
return matrix
for row_idx in range(2, numRows):
matrix.append(
[1]
+ [
matrix[row_idx - 1][col_idx - 1]
+ matrix[row_idx - 1][col_idx]
for col_idx in range(1, row_idx)
]
+ [1]
)
return matrix
def test():
executors = [
CreateUpdate,
Append,
]
tests = [
[
5,
[
[1],
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1],
],
],
[1, [[1]]],
[2, [[1], [1, 1]]],
[3, [[1], [1, 1], [1, 2, 1]]],
]
for executor in executors:
start = timeit.default_timer()
for _ in range(1):
for col, t in enumerate(tests):
sol = executor()
result = sol.generate(t[0])
exp = t[1]
assert result == exp, (
f"\033[93m» {result} <> {exp}\033[91m for"
+ f" test {col} 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()