def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) # should output 3 x = lca(tree, tree.left, tree.right) assert x.data == 3 print(x.data) # should output 5 x = lca(tree, tree.right.left, tree.right.right) assert x.data == 5 print(x.data) # should output 5 x = lca(tree, tree.right, tree.right.right) assert x.data == 5 print(x.data) # should output 3 x = lca(tree, tree, tree.left.left) assert x.data == 3 print(x.data) # should output 2 x = lca(tree, tree.left, tree.left.left) assert x.data == 2 print(x.data)
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) assert has_path_sum(tree, 3) tree.left = BinaryTreeNode(2) assert has_path_sum(tree, 5) tree.left.left = BinaryTreeNode(1) assert has_path_sum(tree, 6) tree.right = BinaryTreeNode(5) assert has_path_sum(tree, 8) assert not has_path_sum(tree, 7) tree.right.left = BinaryTreeNode(4) assert has_path_sum(tree, 12) assert not has_path_sum(tree, 1) assert not has_path_sum(tree, 3) assert not has_path_sum(tree, 5) tree.right.right = BinaryTreeNode(6) assert has_path_sum(tree, 6) assert not has_path_sum(tree, 7) assert has_path_sum(tree, 14) assert not has_path_sum(tree, -1) assert not has_path_sum(tree, 2**64 - 1) assert not has_path_sum(tree, -2**64)
def small_test(): root = BinaryTreeNode(5) assert not pair_includes_ancestor_and_descendant_of_m(root, root, root) root.left = BinaryTreeNode(2) root.left.right = BinaryTreeNode(4) assert not pair_includes_ancestor_and_descendant_of_m(root, root.left, root.left.right) assert pair_includes_ancestor_and_descendant_of_m(root, root.left.right, root.left) # Example of the first figure of BST chapter. root = BinaryTreeNode(19) root.left = BinaryTreeNode(7) root.left.left = BinaryTreeNode(3) root.left.left.left = BinaryTreeNode(2) root.left.left.right = BinaryTreeNode(5) root.left.right = BinaryTreeNode(11) root.left.right.right = BinaryTreeNode(17) root.left.right.right.left = BinaryTreeNode(13) root.right = BinaryTreeNode(43) root.right.left = BinaryTreeNode(23) root.right.left.right = BinaryTreeNode(37) root.right.left.right.left = BinaryTreeNode(29) root.right.left.right.left.right = BinaryTreeNode(31) root.right.left.right.right = BinaryTreeNode(41) root.right.right = BinaryTreeNode(47) root.right.right.right = BinaryTreeNode(53) assert not pair_includes_ancestor_and_descendant_of_m(root.right, root.left, root.right.left) assert pair_includes_ancestor_and_descendant_of_m( root, root.right.left.right.left.right, root.right.left)
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) tree_traversal(tree)
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) res = postorder_traversal(tree) golden_res = generate_postorder(tree) assert list(res) == golden_res
def main(): # 3 # 2 5 # 1 4 7 root = BinaryTreeNode(3) root.left = BinaryTreeNode(2) root.left.left = BinaryTreeNode(1) root.right = BinaryTreeNode(5) root.right.left = BinaryTreeNode(4) root.right.right = BinaryTreeNode(7) assert find_first_greater_than_k(root, 1) is root.left assert find_first_greater_than_k(root, 5) is root.right.right assert find_first_greater_than_k(root, 6) is root.right.right assert not find_first_greater_than_k(root, 7)
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) # should output 1 2 3 4 5 6 inorder_traversal(tree) golden_res = [1, 2, 3, 4, 5, 6] assert result == golden_res
def main(): # 1 # 1 0 # 0 1 0 root = BinaryTreeNode(1) assert sum_root_to_leaf(root) == 1 root.left = BinaryTreeNode(1) assert sum_root_to_leaf(root) == 3 root.left.left = BinaryTreeNode(0) assert sum_root_to_leaf(root) == 6 root.right = BinaryTreeNode(0) assert sum_root_to_leaf(root) == 8 root.right.left = BinaryTreeNode(1) assert sum_root_to_leaf(root) == 11 root.right.right = BinaryTreeNode(0) assert sum_root_to_leaf(root) == 15
def build_min_height_bst_from_sorted_subarray(start, end): if start >= end: return None mid = (start + end) // 2 return BinaryTreeNode( A[mid], build_min_height_bst_from_sorted_subarray(start, mid), build_min_height_bst_from_sorted_subarray(mid + 1, end))
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) assert 3 == find_LCA(tree, tree.left.left, tree.right.left).data assert 5 == find_LCA(tree, tree.right.left, tree.right.right).data assert 2 == find_LCA(tree, tree.left.left, tree.left).data
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) res = preorder_traversal(tree) golden_res = generate_preorder(tree) assert res == golden_res
def reconstruct_preorder_helper(preorder_iter): node = next(preorder_iter) if (node is None): return None left = reconstruct_preorder_helper(preorder_iter) right = reconstruct_preorder_helper(preorder_iter) return BinaryTreeNode(node, left, right)
def generate_all_binary_trees_pythonic(num_nodes): return [ BinaryTreeNode(0, left, right) for num_left_tree_nodes in range(num_nodes) for left in generate_all_binary_trees(num_left_tree_nodes) for right in generate_all_binary_trees(num_nodes - 1 - num_left_tree_nodes) ] or [None]
def main(): # 3 # 2 4 # 1 5 6 almost_bst = BinaryTreeNode(3) almost_bst.left = BinaryTreeNode(2) almost_bst.left.left = BinaryTreeNode(1) almost_bst.right = BinaryTreeNode(4) almost_bst.right.left = BinaryTreeNode(5) almost_bst.right.right = BinaryTreeNode(6) reconstruct_bst(almost_bst) result = generate_inorder(almost_bst) print(*result) assert all(result[i] <= result[i + 1] for i in range(len(result) - 1))
def generate_rand_binary_tree(n, is_unique=False): if not n: return None l = [] temp_n = n root = BinaryTreeNode(n if is_unique else random.randrange(temp_n)) n -= 1 l.append((root, 'left')) l.append((root, 'right')) while n: x = random.randrange(len(l)) node = BinaryTreeNode(n if is_unique else random.randrange(temp_n)) setattr(l[x][0], l[x][1], node) l.append((node, 'left')) l.append((node, 'right')) del l[x] n -= 1 return root
def main(): # A min-first BST # 1 # 2 4 # 3 5 7 tree = BinaryTreeNode(1) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(3) tree.right = BinaryTreeNode(4) tree.right.left = BinaryTreeNode(5) tree.right.right = BinaryTreeNode(7) assert search_min_first_bst(tree, 1) assert search_min_first_bst(tree, 3) assert search_min_first_bst(tree, 5) assert not search_min_first_bst(tree, 6)
def main(): # 3 # 2 5 # 1 4 6 root = BinaryTreeNode(3) root.left = BinaryTreeNode(2) root.left.left = BinaryTreeNode(1) root.right = BinaryTreeNode(5) root.right.left = BinaryTreeNode(4) root.right.right = BinaryTreeNode(6) k = 0 ans = find_k_unbalanced_node(root, k) assert ans.data == 2 if ans: print(ans.data)
def main(): # balanced binary tree test # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode() tree.left = BinaryTreeNode() tree.left.left = BinaryTreeNode() tree.right = BinaryTreeNode() tree.right.left = BinaryTreeNode() tree.right.right = BinaryTreeNode() assert is_balanced_binary_tree(tree) print(is_balanced_binary_tree(tree)) # Non-balanced binary tree test. tree = BinaryTreeNode() tree.left = BinaryTreeNode() tree.left.left = BinaryTreeNode() assert not is_balanced_binary_tree(tree) print(is_balanced_binary_tree(tree))
def reconstruct_preorder_helper(preorder_iter): subtree_key = next(preorder_iter) if subtree_key is None: return None # Note that reconstruct_preorder_helper updates preorder_iter. So the # order of following two calls are critical. left_subtree = reconstruct_preorder_helper(preorder_iter) right_subtree = reconstruct_preorder_helper(preorder_iter) return BinaryTreeNode(subtree_key, left_subtree, right_subtree)
def simple_test(): symm_tree = BinaryTreeNode() assert is_symmetric(symm_tree) symm_tree.left = BinaryTreeNode() assert not is_symmetric(symm_tree) symm_tree.right = BinaryTreeNode() assert is_symmetric(symm_tree) symm_tree.right.right = BinaryTreeNode() assert not is_symmetric(symm_tree)
def rebuild_bst_from_preorder(preorder_sequence): if not preorder_sequence: return None transition_point = next( (i for i, a in enumerate(preorder_sequence) if a > preorder_sequence[0]), len(preorder_sequence)) return BinaryTreeNode( preorder_sequence[0], rebuild_bst_from_preorder(preorder_sequence[1:transition_point]), rebuild_bst_from_preorder(preorder_sequence[transition_point:]))
def main(): # 3 # 2 5 # 1 4 6 # 10 # 13 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.left.left.left = BinaryTreeNode(10) tree.left.left.left.right = BinaryTreeNode(13) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) # should output 3 # 2 5 # 1 4 6 # 10 # 13 assert binary_tree_depth_order(tree) == [[3], [2, 5], [1, 4, 6], [10], [13]]
def main(): simple_test() # 3 # 2 5 # 1 0 4 6 # -1 -2 tree = BinaryTreeNode(3) assert create_output_list(exterior_binary_tree(tree)) == [3] tree.left = BinaryTreeNode(2) assert create_output_list(exterior_binary_tree(tree)) == [3, 2] tree.left.right = BinaryTreeNode(0) tree.left.right.left = BinaryTreeNode(-1) tree.left.right.right = BinaryTreeNode(-2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) assert create_output_list( exterior_binary_tree(tree)) == [3, 2, 1, -1, -2, 4, 6, 5]
def main(): # 3 # 2 6 # 1 4 6 root = BinaryTreeNode(3) root.left = BinaryTreeNode(2) root.left.left = BinaryTreeNode(1) root.right = BinaryTreeNode(6) root.right.left = BinaryTreeNode(4) root.right.right = BinaryTreeNode(6) assert not find_first_equal_k(root, 7) assert (find_first_equal_k(root, 6).data == 6 and find_first_equal_k(root, 6).right.data == 6) # 3 # 3 5 # 2 5 6 root = BinaryTreeNode(3) root.left = BinaryTreeNode(3) root.left.left = BinaryTreeNode(2) root.right = BinaryTreeNode(5) root.right.left = BinaryTreeNode(5) root.right.right = BinaryTreeNode(6) assert not find_first_equal_k(root, 7) assert find_first_equal_k(root, 3) is root.left assert find_first_equal_k(root, 5) is root.right.left assert find_first_equal_k(root, 6).data == 6
def main(): # 3 # 2 5 # 1 4 6 root = BinaryTreeNode(3) root.left = BinaryTreeNode(2) root.left.left = BinaryTreeNode(1) root.right = BinaryTreeNode(5) root.right.left = BinaryTreeNode(4) root.right.right = BinaryTreeNode(6) L = bst_to_doubly_linked_list(root) curr = L pre = float('-inf') while curr: assert pre <= curr.data print(curr.data) pre = curr.data curr = curr.right
def insert(self, key): if self.empty(): self._root = BinaryTreeNode(key) else: parent = None curr = self._root while curr: parent = curr if key == curr.data: # key already present, no duplicates to be added. return False elif key < curr.data: curr = curr.left else: # key > curr.data. curr = curr.right # Inserts key according to key and parent. if key < parent.data: parent.left = BinaryTreeNode(key) else: parent.right = BinaryTreeNode(key) return True
def test(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) # should output True. assert is_binary_tree_bst(tree) assert is_binary_tree_bst_alternative(tree) # 10 # 2 5 # 1 4 6 tree.data = 10 # should output False. assert not is_binary_tree_bst(tree) assert not is_binary_tree_bst_alternative(tree) # should output True. assert is_binary_tree_bst(None) assert is_binary_tree_bst_alternative(None)
def main(): small_test() # 3 # 2 5 # 1 4 6 root = BinaryTreeNode(3) root.left = BinaryTreeNode(2) root.left.left = BinaryTreeNode(1) root.right = BinaryTreeNode(5) root.right.left = BinaryTreeNode(4) root.right.right = BinaryTreeNode(6) assert pair_includes_ancestor_and_descendant_of_m(root, root.right.right, root.right) assert pair_includes_ancestor_and_descendant_of_m(root.right.right, root, root.right) assert not pair_includes_ancestor_and_descendant_of_m(root, root.right, root.right.right) assert not pair_includes_ancestor_and_descendant_of_m(root.right, root, root.right.right) assert (not pair_includes_ancestor_and_descendant_of_m( root.right.left, root.right.right, root.right)) assert (not pair_includes_ancestor_and_descendant_of_m( root.right.left, root.left.left, root.right))
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) # should output True. assert is_binary_tree_BST(tree) == True print(is_binary_tree_BST(tree)) # 10 # 2 5 # 1 4 6 tree.data = 10 # should output False. assert not is_binary_tree_BST(tree) print(is_binary_tree_BST(tree)) # should output True. assert is_binary_tree_BST(None) == True print(is_binary_tree_BST(None))
def generate_all_binary_trees(num_nodes): if num_nodes == 0: # Empty tree, add as a None. return [None] result = [] for num_left_tree_nodes in range(num_nodes): num_right_tree_nodes = num_nodes - 1 - num_left_tree_nodes left_subtrees = generate_all_binary_trees(num_left_tree_nodes) right_subtrees = generate_all_binary_trees(num_right_tree_nodes) # Generates all combinations of left_subtrees and right_subtrees. result += [ BinaryTreeNode(0, left, right) for left in left_subtrees for right in right_subtrees ] return result
def rebuild_bst_from_preorder_on_value_range(lower_bound, upper_bound): if root_idx[0] == len(preorder_sequence): return None root = preorder_sequence[root_idx[0]] if not lower_bound <= root <= upper_bound: return None root_idx[0] += 1 # Note that rebuild_bst_from_preorder_on_value_range updates root_idx[0]. # So the order of following two calls are critical. left_subtree = rebuild_bst_from_preorder_on_value_range( lower_bound, root) right_subtree = rebuild_bst_from_preorder_on_value_range( root, upper_bound) return BinaryTreeNode(root, left_subtree, right_subtree)
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) L = create_list_of_leaves(tree) assert len(L) == 1 and L[0].data == 2 tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) L = create_list_of_leaves(tree) output = [] # should output 1, 4, 6 for l in L: output.append(l.data) print(l.data) golden_res = [1, 4, 6] assert output == golden_res
def merge_two_sorted_lists(A, B): sorted_head = BinaryTreeNode() tail = sorted_head AB = [A, B] while all(AB): A_or_B = 0 if AB[0].data < AB[1].data else 1 tail.right = AB[A_or_B] tail = tail.right # Resets tail to the last node. AB[A_or_B] = tail.right if AB[0]: # Appends the remaining of A. tail.right = AB[0] elif AB[1]: # Appends the remaining of B. tail.right = AB[1] return sorted_head.right
def binary_tree_from_preorder_inorder_helper(preorder_start, preorder_end, inorder_start, inorder_end): if preorder_end <= preorder_start or inorder_end <= inorder_start: return None root_inorder_idx = node_to_inorder_idx[preorder[preorder_start]] left_subtree_size = root_inorder_idx - inorder_start return BinaryTreeNode( preorder[preorder_start], # Recursively builds the left subtree. binary_tree_from_preorder_inorder_helper( preorder_start + 1, preorder_start + 1 + left_subtree_size, inorder_start, root_inorder_idx), # Recursively builds the right subtree. binary_tree_from_preorder_inorder_helper( preorder_start + 1 + left_subtree_size, preorder_end, root_inorder_idx + 1, inorder_end))
def main(): small_test() # 3 # 2 5 # 1 4 6 root = BinaryTreeNode(3) root.left = BinaryTreeNode(2) root.left.left = BinaryTreeNode(1) root.right = BinaryTreeNode(5) root.right.left = BinaryTreeNode(4) root.right.right = BinaryTreeNode(6) assert pair_includes_ancestor_and_descendant_of_m(root, root.right.right, root.right) assert pair_includes_ancestor_and_descendant_of_m(root.right.right, root, root.right) assert not pair_includes_ancestor_and_descendant_of_m( root, root.right, root.right.right) assert not pair_includes_ancestor_and_descendant_of_m( root.right, root, root.right.right) assert (not pair_includes_ancestor_and_descendant_of_m( root.right.left, root.right.right, root.right)) assert (not pair_includes_ancestor_and_descendant_of_m( root.right.left, root.left.left, root.right))
def reconstruct_post_in_orders_helper(post_order, post_s, post_e, in_s, in_e, in_entry_idx_map): if post_e > post_s and in_e > in_s: idx = in_entry_idx_map[post_order[post_e - 1]] left_tree_size = idx - in_s return BinaryTreeNode( post_order[post_e - 1], # Recursively builds the left subtree. reconstruct_post_in_orders_helper(post_order, post_s, post_s + left_tree_size, in_s, idx, in_entry_idx_map), # Recursively builds the right subtree. reconstruct_post_in_orders_helper(post_order, post_s + left_tree_size, post_e - 1, idx + 1, in_e, in_entry_idx_map)) return None
def preorder_inorder_helper(preorder_start, preorder_end, inorder_start, inorder_end): if (preorder_end <= preorder_start or inorder_end <= inorder_start): return None root_index_inorder = inorder_indexes[preorder[preorder_start]] left_subtree_size = root_index_inorder - inorder_start return BinaryTreeNode( preorder[preorder_start], preorder_inorder_helper( preorder_start + 1, preorder_start + 1 + left_subtree_size, inorder_start, root_index_inorder, ), preorder_inorder_helper( preorder_start + 1 + left_subtree_size, preorder_end, root_index_inorder + 1, inorder_end, ))
def main(): # 3 # 2 5 # 1 4 6 L = BinaryTreeNode(3) L.left = BinaryTreeNode(2) L.left.left = BinaryTreeNode(1) L.right = BinaryTreeNode(5) L.right.left = BinaryTreeNode(4) L.right.right = BinaryTreeNode(6) # 7 # 2 8 # 0 R = BinaryTreeNode(7) R.left = BinaryTreeNode(2) R.left.left = BinaryTreeNode(0) R.right = BinaryTreeNode(8) root = merge_two_bsts(L, R) # should output 0 1 2 2 3 4 5 6 7 8 print_bst_inorder(root, float('-inf'))
def main(): # 3 # 2 5 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(2) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(5) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) if len(sys.argv) == 2: k = int(sys.argv[1]) else: k = random.randint(1, 6) print('k =', k) ans = find_k_largest_in_bst(tree, k) print(*ans, sep='\n') for i in range(1, len(ans)): assert ans[i - 1] >= ans[i] ans = find_k_largest_in_bst(tree, 2) assert ans[0] == 6 assert ans[1] == 5 # 3 # 3 4 # 1 4 6 tree = BinaryTreeNode(3) tree.left = BinaryTreeNode(3) tree.left.left = BinaryTreeNode(1) tree.right = BinaryTreeNode(4) tree.right.left = BinaryTreeNode(4) tree.right.right = BinaryTreeNode(6) ans = find_k_largest_in_bst(tree, 3) assert ans[0] == 6 assert ans[1] == 4 assert ans[2] == 4
def main(): simple_test() # Non symmetric tree test. # 3 # 2 5 # 1 4 6 non_symm_tree = BinaryTreeNode() non_symm_tree.left = BinaryTreeNode() non_symm_tree.left.left = BinaryTreeNode() non_symm_tree.right = BinaryTreeNode() non_symm_tree.right.left = BinaryTreeNode() non_symm_tree.right.right = BinaryTreeNode() assert not is_symmetric(non_symm_tree) print(is_symmetric(non_symm_tree)) # Symmetric tree test. symm_tree = BinaryTreeNode() symm_tree.left = BinaryTreeNode() symm_tree.right = BinaryTreeNode() assert is_symmetric(symm_tree) print(is_symmetric(symm_tree)) # Empty tree test. symm_tree = None assert is_symmetric(symm_tree) print(is_symmetric(symm_tree))