Solve InterviewCake's balanced-binary-tree problem
Write a predicate for determining if a binary tree is "super balanced", which means that the depths of all of the tree's leaves are equal or differ by at most one.
This commit is contained in:
		
							parent
							
								
									0f82a527de
								
							
						
					
					
						commit
						47a11b76a2
					
				
					 2 changed files with 128 additions and 2 deletions
				
			
		
							
								
								
									
										126
									
								
								scratch/deepmind/part_two/balanced-binary-tree.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								scratch/deepmind/part_two/balanced-binary-tree.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,126 @@ | ||||||
|  | import unittest | ||||||
|  | from collections import deque | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # is_balanced :: Node(a) -> Bool | ||||||
|  | def is_balanced(node): | ||||||
|  |     q = deque() | ||||||
|  |     q.append((0, node)) | ||||||
|  |     mn, mx = None, None | ||||||
|  | 
 | ||||||
|  |     while q: | ||||||
|  |         depth, node = q.popleft() | ||||||
|  |         # Current node is a leaf node | ||||||
|  |         if not node.left and not node.right: | ||||||
|  |             mx = depth if mx is None else max(mx, depth) | ||||||
|  |             mn = depth if mn is None else min(mn, depth) | ||||||
|  |             if mx - mn > 1: | ||||||
|  |                 return False | ||||||
|  |         if node.left: | ||||||
|  |             q.append((depth + 1, node.left)) | ||||||
|  |         if node.right: | ||||||
|  |             q.append((depth + 1, node.right)) | ||||||
|  | 
 | ||||||
|  |     return mx - mn <= 1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Tests | ||||||
|  | class Test(unittest.TestCase): | ||||||
|  |     class BinaryTreeNode(object): | ||||||
|  |         def __init__(self, value): | ||||||
|  |             self.value = value | ||||||
|  |             self.left = None | ||||||
|  |             self.right = None | ||||||
|  | 
 | ||||||
|  |         def insert_left(self, value): | ||||||
|  |             self.left = Test.BinaryTreeNode(value) | ||||||
|  |             return self.left | ||||||
|  | 
 | ||||||
|  |         def insert_right(self, value): | ||||||
|  |             self.right = Test.BinaryTreeNode(value) | ||||||
|  |             return self.right | ||||||
|  | 
 | ||||||
|  |     def test_full_tree(self): | ||||||
|  |         tree = Test.BinaryTreeNode(5) | ||||||
|  |         left = tree.insert_left(8) | ||||||
|  |         right = tree.insert_right(6) | ||||||
|  |         left.insert_left(1) | ||||||
|  |         left.insert_right(2) | ||||||
|  |         right.insert_left(3) | ||||||
|  |         right.insert_right(4) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertTrue(result) | ||||||
|  | 
 | ||||||
|  |     def test_both_leaves_at_the_same_depth(self): | ||||||
|  |         tree = Test.BinaryTreeNode(3) | ||||||
|  |         left = tree.insert_left(4) | ||||||
|  |         right = tree.insert_right(2) | ||||||
|  |         left.insert_left(1) | ||||||
|  |         right.insert_right(9) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertTrue(result) | ||||||
|  | 
 | ||||||
|  |     def test_leaf_heights_differ_by_one(self): | ||||||
|  |         tree = Test.BinaryTreeNode(6) | ||||||
|  |         left = tree.insert_left(1) | ||||||
|  |         right = tree.insert_right(0) | ||||||
|  |         right.insert_right(7) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertTrue(result) | ||||||
|  | 
 | ||||||
|  |     def test_leaf_heights_differ_by_two(self): | ||||||
|  |         tree = Test.BinaryTreeNode(6) | ||||||
|  |         left = tree.insert_left(1) | ||||||
|  |         right = tree.insert_right(0) | ||||||
|  |         right_right = right.insert_right(7) | ||||||
|  |         right_right.insert_right(8) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertFalse(result) | ||||||
|  | 
 | ||||||
|  |     def test_three_leaves_total(self): | ||||||
|  |         tree = Test.BinaryTreeNode(1) | ||||||
|  |         left = tree.insert_left(5) | ||||||
|  |         right = tree.insert_right(9) | ||||||
|  |         right.insert_left(8) | ||||||
|  |         right.insert_right(5) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertTrue(result) | ||||||
|  | 
 | ||||||
|  |     def test_both_subtrees_superbalanced(self): | ||||||
|  |         tree = Test.BinaryTreeNode(1) | ||||||
|  |         left = tree.insert_left(5) | ||||||
|  |         right = tree.insert_right(9) | ||||||
|  |         right_left = right.insert_left(8) | ||||||
|  |         right.insert_right(5) | ||||||
|  |         right_left.insert_left(7) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertFalse(result) | ||||||
|  | 
 | ||||||
|  |     def test_both_subtrees_superbalanced_two(self): | ||||||
|  |         tree = Test.BinaryTreeNode(1) | ||||||
|  |         left = tree.insert_left(2) | ||||||
|  |         right = tree.insert_right(4) | ||||||
|  |         left.insert_left(3) | ||||||
|  |         left_right = left.insert_right(7) | ||||||
|  |         left_right.insert_right(8) | ||||||
|  |         right_right = right.insert_right(5) | ||||||
|  |         right_right_right = right_right.insert_right(6) | ||||||
|  |         right_right_right.insert_right(9) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertFalse(result) | ||||||
|  | 
 | ||||||
|  |     def test_only_one_node(self): | ||||||
|  |         tree = Test.BinaryTreeNode(1) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertTrue(result) | ||||||
|  | 
 | ||||||
|  |     def test_linked_list_tree(self): | ||||||
|  |         tree = Test.BinaryTreeNode(1) | ||||||
|  |         right = tree.insert_right(2) | ||||||
|  |         right_right = right.insert_right(3) | ||||||
|  |         right_right.insert_right(4) | ||||||
|  |         result = is_balanced(tree) | ||||||
|  |         self.assertTrue(result) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | unittest.main(verbosity=2) | ||||||
|  | @ -21,7 +21,7 @@ | ||||||
| ** DONE Top Scores | ** DONE Top Scores | ||||||
| ** DONE Merging Meeting Times | ** DONE Merging Meeting Times | ||||||
| * Trees and graphs | * Trees and graphs | ||||||
| ** TODO Balanced Binary Tree | ** DONE Balanced Binary Tree | ||||||
| ** TODO Binary Search Tree Checker | ** TODO Binary Search Tree Checker | ||||||
| ** TODO 2nd Largest Item in a Binary Search Tree | ** TODO 2nd Largest Item in a Binary Search Tree | ||||||
| ** TODO Graph Coloring | ** TODO Graph Coloring | ||||||
|  | @ -32,7 +32,7 @@ | ||||||
| ** TODO Compute nth Fibonacci Number | ** TODO Compute nth Fibonacci Number | ||||||
| ** TODO Making Change | ** TODO Making Change | ||||||
| ** TODO The Cake Thief | ** TODO The Cake Thief | ||||||
| ** TODO Balanced Binary Tree | ** DONE Balanced Binary Tree | ||||||
| ** TODO Binary Search Tree Checker | ** TODO Binary Search Tree Checker | ||||||
| ** TODO 2nd Largest Item in a Binary Search Tree | ** TODO 2nd Largest Item in a Binary Search Tree | ||||||
| * Queues and stacks | * Queues and stacks | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue