Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 112 additions & 22 deletions binary_search_tree/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,46 +14,136 @@ class Tree:
def __init__(self):
self.root = None

# Time Complexity:
# Space Complexity:
# Time Complexity: 0(log(n)
# Space Complexity: 0(1)
def add(self, key, value = None):
pass
added = TreeNode(key, value)
if not self.root:
self.root = added

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do not return after this guard close, you'll enter into an infinite loop

Suggested change
self.root = added
self.root = added
return added


parent = self.root
while True:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally try to avoid while loops whose conditions can never be Falsey. With while loops, we always want the body of the while loop to be making progress toward the condition being False.

How might you refactor you code to eliminate this? Hint: Look at your find function

if added.key > parent.key:
if not parent.right:
parent.right = added
return added
else:
parent = parent.right
elif added.key <= parent.key:
if not parent.left:
parent.left = added
return added
else:
parent = parent.left
else:
return "something went wrong"
Comment on lines +38 to +39

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't necessary

Suggested change
else:
return "something went wrong"



# Time Complexity:
# Space Complexity:
# Time Complexity: 0(log(n))
# Space Complexity: 0(1)
def find(self, key):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass
current = self.root
while current:
if key == current.key:
return current.value
elif key <= current.key:
current = current.left
elif key > current.key:
current = current.right

return None

# Time Complexity:
# Space Complexity:
def inorder_helper(self, current, nodes = None):
if nodes is None:
nodes = []
if current:
self.inorder_helper(current.left, nodes)
nodes.append({
"key": current.key,
"value": current.value
})
self.inorder_helper(current.right, nodes)
return nodes

# Time Complexity: O(n)
# Space Complexity: O(n)
def inorder(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass
return self.inorder_helper(self.root)

# Time Complexity:
# Space Complexity:
def preorder_helper(self, current, nodes = None):
if nodes is None:
nodes = []
if current:
nodes.append({
"key": current.key,
"value": current.value
})
self.preorder_helper(current.left, nodes)
self.preorder_helper(current.right, nodes)
return nodes

# Time Complexity: O(n)
# Space Complexity: O(n)
def preorder(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass
return self.preorder_helper(self.root)

# Time Complexity:
# Space Complexity:
def postorder_helper(self, current, nodes = None):
if nodes is None:
nodes = []
if current:
self.postorder_helper(current.left, nodes)
self.preorder_helper(current.right, nodes)
nodes.append({
"key": current.key,
"value": current.value
})
return nodes

# Time Complexity: O(n)
# Space Complexity: O(n)
def postorder(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass
return self.postorder_helper(self.root)

# Time Complexity:
# Space Complexity:
def height(self):
pass
def height_helper(self, current, nodes = None):
if nodes is None:
nodes = []
if current:
self.height_helper(current.left, nodes)
if current.left is None and current.right is None:
nodes.append(current.key)
self.height_helper(current.right, nodes)
return nodes

def get_count(self, key):
current = self.root
count = 0
while current:
count += 1
if key == current.key:
return count
elif key > current.key:
current = current.right
elif key < current.key:
current = current.left
return None

# Time Complexity: O(nlog(n))
# Space Complexity: 0(m) -> m == # of nodes
def height(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✨ This time and space complexity is correct for your solution!

You could refactor your code to achieve an O(n) time and space solution. Instead of having height_helper return a list, have it return an integer. When you make a recursive call on the left/right subtree, you know that your height is 1 + the height of the deepest subtree. So you can say that the height is 1 + max(height of left subtree, height of right subtree).

ends = self.height_helper(self.root)
max = 0
for end in ends:
height = self.get_count(end)
if height > max:
max = height
return max

# # Optional Method
# # Time Complexity:
# # Space Complexity:
def bfs(self):
pass




# # Useful for printing
def to_s(self):
return f"{self.inorder()}"
75 changes: 37 additions & 38 deletions tests/test_binary_search_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_add_and_find(tree_with_nodes):
assert tree_with_nodes.find(15) == "Ada"
assert tree_with_nodes.find(3) == "Paul"


#
def test_can_find_leaf_nodes(tree_with_nodes):
assert tree_with_nodes.find(1) == "Mary"
assert tree_with_nodes.find(25) == "Kari"
Expand Down Expand Up @@ -153,7 +153,6 @@ def test_postorder_on_tree_with_nodes(tree_with_nodes):
answer = tree_with_nodes.postorder()
assert answer == expected_answer


def test_height_of_empty_tree_is_zero(empty_tree):
assert empty_tree.height() == 0

Expand Down Expand Up @@ -201,39 +200,39 @@ def test_will_report_height_of_unbalanced_tree():
unbalanced_tree.add(100, "Karla")

assert unbalanced_tree.height() == 5


def test_bfs_with_empty_tree(empty_tree):
assert empty_tree.bfs() == []


def test_bfs_with_tree_with_nodes(tree_with_nodes):
expected_answer = [
{
"key": 5,
"value": "Peter"
},
{
"key": 3,
"value": "Paul"
},
{
"key": 10,
"value": "Karla"
},
{
"key": 1,
"value": "Mary"
},
{
"key": 15,
"value": "Ada"
},
{
"key": 25,
"value": "Kari"
}
]

answer = tree_with_nodes.bfs()
assert answer == expected_answer
#
#
# def test_bfs_with_empty_tree(empty_tree):
# assert empty_tree.bfs() == []
#
#
# def test_bfs_with_tree_with_nodes(tree_with_nodes):
# expected_answer = [
# {
# "key": 5,
# "value": "Peter"
# },
# {
# "key": 3,
# "value": "Paul"
# },
# {
# "key": 10,
# "value": "Karla"
# },
# {
# "key": 1,
# "value": "Mary"
# },
# {
# "key": 15,
# "value": "Ada"
# },
# {
# "key": 25,
# "value": "Kari"
# }
# ]
#
# answer = tree_with_nodes.bfs()
# assert answer == expected_answer