Skip to content

Commit 41e79fc

Browse files
Add utility functions
1 parent 4ba5361 commit 41e79fc

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

tests/utils.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,36 @@ def create_binary_tree_from_list(l: list[int | None]) -> TreeNode | None:
7272
tree in breadth-first search order.
7373
7474
NOTE: Gaps in the binary tree should be denoted by `None`.
75+
76+
NOTE: This function requires that the list represent a complete binary
77+
tree:
78+
1. All levels must be completely filled from left to right, except
79+
possibly the last level.
80+
2. The last level must have nodes filled from left to right without gaps.
81+
82+
This means that gaps must be denoted by `None`, except for gaps to the
83+
right of the last node in the last level.
84+
85+
For example, given the following tree:
86+
87+
1
88+
89+
/ \
90+
2 3
91+
● ●
92+
/ \
93+
4 5
94+
● ●
95+
/ \
96+
6 7
97+
● ●
98+
99+
The list representation would be:
100+
101+
[1, 2, 3, None, None, 4, 5, None, None, None, None, 6, 7]
102+
103+
For functions that do not require that the list represent a complete binary
104+
tree, see `serialize_binary_tree()` and `deserialize_binary_tree()`.
75105
"""
76106
if not l:
77107
return None
@@ -131,6 +161,93 @@ def create_bfs_list_from_binary_tree(*, root: TreeNode | None, values_only: bool
131161
return l
132162

133163

164+
def create_bfs_list_from_binary_tree_with_gaps(
165+
*, root: TreeNode | None, values_only: bool = True
166+
) -> list[TreeNode | T | None]:
167+
"""
168+
Same as `create_bfs_list_from_binary_tree()`, but accounts for gaps. Gaps
169+
in the tree should be denoted by `None`.
170+
"""
171+
if not root:
172+
return []
173+
174+
l: list[TreeNode | T | None] = []
175+
q: deque[TreeNode | None] = deque([root])
176+
177+
while q:
178+
curr: TreeNode | None = q.popleft()
179+
if curr and values_only:
180+
l.append(curr.val)
181+
elif curr:
182+
l.append(curr)
183+
else:
184+
l.append(None)
185+
if curr:
186+
q.append(curr.left)
187+
q.append(curr.right)
188+
189+
# Remove trailing 'None' values.
190+
while not l[-1]:
191+
l.pop()
192+
193+
return l
194+
195+
196+
def serialize_binary_tree(root: TreeNode[T] | None) -> list[T | None]:
197+
"""
198+
Serializes a binary tree similar to LeetCode.
199+
"""
200+
l: list[T | None] = []
201+
202+
if not root:
203+
return l
204+
205+
q: deque[TreeNode[T] | None] = deque([root])
206+
207+
while q:
208+
curr: TreeNode[T] | None = q.popleft()
209+
if curr:
210+
l.append(curr.val)
211+
else:
212+
l.append(None)
213+
if curr:
214+
q.append(curr.left)
215+
q.append(curr.right)
216+
217+
# Remove trailing 'None' values.
218+
while not l[-1]:
219+
l.pop()
220+
221+
return l
222+
223+
224+
def deserialize_binary_tree(l: list[T | None]) -> TreeNode[T] | None:
225+
"""
226+
Deserializes a binary tree similar to LeetCode.
227+
"""
228+
if not l or not l[0]:
229+
return None
230+
231+
root = TreeNode(val=l[0])
232+
q: deque[TreeNode] = deque([root])
233+
i = 1
234+
235+
while q and i < len(l):
236+
curr: TreeNode = q.popleft()
237+
if l[i] is not None:
238+
left = TreeNode(val=l[i])
239+
curr.left = left
240+
q.append(left)
241+
i += 1
242+
if l[i] is not None:
243+
right = TreeNode(val=l[i])
244+
curr.right = right
245+
q.append(right)
246+
i += 1
247+
248+
return root
249+
250+
134251
def assert_tree(root: TreeNode | None, exp: list[T | None]) -> None:
135252
"""
136253
Given a list of values in level-order traversal, assert that the tree

0 commit comments

Comments
 (0)