Skip to content

Commit b96097d

Browse files
Add utils.py; update unit tests
1 parent 2119921 commit b96097d

7 files changed

+161
-34
lines changed

tests/test_invert_binary_tree.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@
77
from unittest import TestCase
88

99
from src.invert_binary_tree import Solution
10-
from tests.utils import bfs, create_binary_tree
10+
from tests.utils import create_bfs_list_from_binary_tree, create_binary_tree_from_list
1111

1212

1313
class TestSolution(TestCase):
1414
def test_1(self):
1515
exp = [4, 7, 2, 9, 6, 3, 1]
16-
t = create_binary_tree([4, 2, 7, 1, 3, 6, 9])
17-
assert bfs(Solution().invertTree(t)) == exp
16+
t = create_binary_tree_from_list([4, 2, 7, 1, 3, 6, 9])
17+
assert create_bfs_list_from_binary_tree(Solution().invertTree(t)) == exp
1818

1919
def test_2(self):
2020
exp = [2, 3, 1]
21-
t = create_binary_tree([2, 1, 3])
22-
assert bfs(Solution().invertTree(t)) == exp
21+
t = create_binary_tree_from_list([2, 1, 3])
22+
assert create_bfs_list_from_binary_tree(Solution().invertTree(t)) == exp
2323

2424
def test_3(self):
2525
exp = []
26-
t = create_binary_tree([])
27-
assert bfs(Solution().invertTree(t)) == exp
26+
t = create_binary_tree_from_list([])
27+
assert create_bfs_list_from_binary_tree(Solution().invertTree(t)) == exp

tests/test_linked_list_cycle.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@
88

99
from src.linked_list_cycle import Solution
1010

11-
from .utils import create_cyclic_linked_list
11+
from .utils import create_cyclic_linked_list_from_list
1212

1313

1414
class TestSolution(TestCase):
1515
def test_1(self):
1616
exp = True
17-
l = create_cyclic_linked_list([3, 2, 0, -4], 1)
17+
l = create_cyclic_linked_list_from_list([3, 2, 0, -4], 1)
1818
assert Solution().hasCycle(l) == exp
1919

2020
def test_2(self):
2121
exp = True
22-
l = create_cyclic_linked_list([1, 2], 0)
22+
l = create_cyclic_linked_list_from_list([1, 2], 0)
2323
assert Solution().hasCycle(l) == exp
2424

2525
def test_3(self):
2626
exp = False
27-
l = create_cyclic_linked_list([1], -1)
27+
l = create_cyclic_linked_list_from_list([1], -1)
2828
assert Solution().hasCycle(l) == exp

tests/test_maximum_depth_of_binary_tree.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
from unittest import TestCase
88

99
from src.maximum_depth_of_binary_tree import Solution
10-
from tests.utils import create_binary_tree
10+
from tests.utils import create_binary_tree_from_list
1111

1212

1313
class TestSolution(TestCase):
1414
def test_1(self):
1515
exp = 3
16-
root = create_binary_tree([3, 9, 20, None, None, 15, 7])
16+
root = create_binary_tree_from_list([3, 9, 20, None, None, 15, 7])
1717
assert Solution().maxDepth(root) == exp
1818

1919
def test_2(self):
2020
exp = 2
21-
root = create_binary_tree([1, None, 2])
21+
root = create_binary_tree_from_list([1, None, 2])
2222
assert Solution().maxDepth(root) == exp

tests/test_same_tree.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@
77
from unittest import TestCase
88

99
from src.same_tree import Solution
10-
from tests.utils import create_binary_tree
10+
from tests.utils import create_binary_tree_from_list
1111

1212

1313
class TestSolution(TestCase):
1414
def test_1(self):
1515
exp = True
16-
p = create_binary_tree([1, 2, 3])
17-
q = create_binary_tree([1, 2, 3])
16+
p = create_binary_tree_from_list([1, 2, 3])
17+
q = create_binary_tree_from_list([1, 2, 3])
1818
assert Solution().isSameTree(p, q) == exp
1919

2020
def test_2(self):
2121
exp = False
22-
p = create_binary_tree([1, 2])
23-
q = create_binary_tree([1, None, 2])
22+
p = create_binary_tree_from_list([1, 2])
23+
q = create_binary_tree_from_list([1, None, 2])
2424
assert Solution().isSameTree(p, q) == exp
2525

2626
def test_3(self):
2727
exp = False
28-
p = create_binary_tree([1, 2, 1])
29-
q = create_binary_tree([1, 1, 2])
28+
p = create_binary_tree_from_list([1, 2, 1])
29+
q = create_binary_tree_from_list([1, 1, 2])
3030
assert Solution().isSameTree(p, q) == exp

tests/test_subtree_of_another_tree.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,30 @@
77
from unittest import TestCase
88

99
from src.subtree_of_another_tree import Solution
10-
from tests.utils import create_binary_tree
10+
from tests.utils import create_binary_tree_from_list
1111

1212

1313
class TestSolution(TestCase):
1414
def test_1(self):
1515
exp = True
16-
r = create_binary_tree([3, 4, 5, 1, 2])
17-
s = create_binary_tree([4, 1, 2])
16+
r = create_binary_tree_from_list([3, 4, 5, 1, 2])
17+
s = create_binary_tree_from_list([4, 1, 2])
1818
assert Solution().isSubtree(r, s) == exp
1919

2020
def test_2(self):
2121
exp = False
22-
r = create_binary_tree([3, 4, 5, 1, 2, None, None, None, None, 0])
23-
s = create_binary_tree([4, 1, 2])
22+
r = create_binary_tree_from_list([3, 4, 5, 1, 2, None, None, None, None, 0])
23+
s = create_binary_tree_from_list([4, 1, 2])
2424
assert Solution().isSubtree(r, s) == exp
2525

2626
def test_3(self):
2727
exp = True
28-
r = create_binary_tree([1, 1])
29-
s = create_binary_tree([1])
28+
r = create_binary_tree_from_list([1, 1])
29+
s = create_binary_tree_from_list([1])
3030
assert Solution().isSubtree(r, s) == exp
3131

3232
def test_4(self):
3333
exp = False
34-
r = create_binary_tree([3, 4, 5, 1, None, 2])
35-
s = create_binary_tree([3, 1, 2])
34+
r = create_binary_tree_from_list([3, 4, 5, 1, None, 2])
35+
s = create_binary_tree_from_list([3, 1, 2])
3636
assert Solution().isSubtree(r, s) == exp

tests/test_validate_binary_search_tree.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@
77
from unittest import TestCase
88

99
from src.validate_binary_search_tree import Solution
10-
from tests.utils import create_binary_tree
10+
from tests.utils import create_binary_tree_from_list
1111

1212

1313
class TestSolution(TestCase):
1414
def test_1(self):
1515
exp = True
16-
root = create_binary_tree([2, 1, 3])
16+
root = create_binary_tree_from_list([2, 1, 3])
1717
assert Solution().isValidBST(root) == exp
1818

1919
def test_2(self):
2020
exp = False
21-
root = create_binary_tree([5, 1, 4, None, None, 3, 6])
21+
root = create_binary_tree_from_list([5, 1, 4, None, None, 3, 6])
2222
assert Solution().isValidBST(root) == exp
2323

2424
def test_3(self):
2525
exp = False
26-
root = create_binary_tree([2, 2, 2])
26+
root = create_binary_tree_from_list([2, 2, 2])
2727
assert Solution().isValidBST(root) == exp

tests/utils.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
"""
2+
Utility functions for testing.
3+
"""
4+
5+
from collections import deque
6+
7+
from src.classes import ListNode, TreeNode
8+
9+
10+
def create_linked_list_from_list(l: list[int]) -> ListNode | None:
11+
"""
12+
Creates a linked list from a list of integers, where each element of the
13+
list becomes a node in the linked list. Returns the head of the linked
14+
list.
15+
"""
16+
if not l:
17+
return None
18+
head = ListNode(l[0])
19+
curr = head
20+
for val in l[1:]:
21+
curr.next = ListNode(val)
22+
curr = curr.next
23+
return head
24+
25+
26+
def create_cyclic_linked_list_from_list(l: list[int], pos: int) -> ListNode | None:
27+
"""
28+
Creates a cyclic linked list from a list of integers. The `pos` parameter
29+
specifies the 0-based index from the list, which represents a node in the
30+
linked list. The last node in the linked list points back to the node at
31+
this position, creating a cycle.
32+
"""
33+
if not l:
34+
return None
35+
head = ListNode(l[0])
36+
curr = head
37+
# `start` is the node that starts the cycle commonly referred to as the
38+
# "cycle entry node" or "loop starting node".
39+
start = None
40+
for i, val in enumerate(l[1:]):
41+
curr.next = ListNode(val)
42+
if i == pos:
43+
start = curr
44+
curr = curr.next
45+
curr.next = start
46+
return head
47+
48+
49+
def create_list_from_linked_list(head: ListNode | None) -> list[int]:
50+
"""
51+
Creates a list of integers from the head of a linked list.
52+
"""
53+
if not head:
54+
return []
55+
l: list[int] = []
56+
while head:
57+
l.append(head.val)
58+
head = head.next
59+
return l
60+
61+
62+
def create_binary_tree_from_list(l: list[int | None]) -> TreeNode | None:
63+
"""
64+
Creates a binary tree from a list of integers, where each element of the
65+
list becomes a node in the binary tree. Returns the root of the binary
66+
tree.
67+
68+
For zero-based arrays, the rule is that a node at position `i` has children
69+
at positions `2*i+1` and `2*i+2`; in the other direction, a node at
70+
position `i` has a parent at position `(i-1)/2` (which rounds down). This
71+
is equivalent to storing a binary tree in an array by reading through the
72+
tree in breadth-first search order.
73+
74+
NOTE: Gaps in the binary tree should be denoted by `None`.
75+
"""
76+
if not l:
77+
return None
78+
return _create_binary_tree_from_list(l, 0)
79+
80+
81+
def _create_binary_tree_from_list(l: list[int | None], i: int) -> TreeNode | None:
82+
"""
83+
Helper function for `create_binary_tree_from_list()`. Given a list of
84+
integers and an index, which represents a node in the binary tree,
85+
recursively create the binary tree.
86+
"""
87+
# If the index is out of bounds of the array, the previous node was a leaf,
88+
# therefore return None.
89+
# If the current node is None, it represents a gap in the binary tree,
90+
# therefore return None.
91+
if i >= len(l) or l[i] is None:
92+
return None
93+
94+
# Create node with current value
95+
node = TreeNode(l[i])
96+
97+
# Recursively build left and right subtrees using child indices.
98+
node.left = _create_binary_tree_from_list(l, 2 * i + 1)
99+
node.right = _create_binary_tree_from_list(l, 2 * i + 2)
100+
101+
return node
102+
103+
104+
def create_bfs_list_from_binary_tree(root: TreeNode | None) -> list[int]:
105+
"""
106+
Creates a list of integers in breadth-first search order given the root
107+
node of a binary tree.
108+
109+
Breadth-first order always attempts to visit the node closest to the root
110+
that it has not already visited. This is also called a level-order
111+
traversal.
112+
"""
113+
if not root:
114+
return []
115+
116+
l: list[int] = []
117+
q: deque[TreeNode] = deque([root])
118+
119+
while q:
120+
curr: TreeNode = q.popleft()
121+
l.append(curr.val)
122+
if curr.left:
123+
q.append(curr.left)
124+
if curr.right:
125+
q.append(curr.right)
126+
127+
return l

0 commit comments

Comments
 (0)