def sorted_array_to_height_balanced_bst(array: List[int]) -> Optional[Node]: size = len(array) if size == 0: return None if size == 1: return Node(array[0]) mid = size // 2 root = Node(array[mid]) root.left = sorted_array_to_height_balanced_bst(array[:mid]) root.right = sorted_array_to_height_balanced_bst(array[mid + 1:]) return root
def _construct_bst( postorder: List[int], start_index: int, end_index: int ) -> Optional[Node]: if end_index < start_index: return None root = Node(postorder[end_index]) left_last_index = find_index_of_smaller(postorder, start_index, end_index) root.left = _construct_bst(postorder, start_index, left_last_index) root.right = _construct_bst( postorder, left_last_index + 1, find_index_of_larger(postorder, left_last_index + 1, end_index), ) return root
def construct_bst(start: int, end: int) -> List[Optional[Node]]: if start > end: return [None] return_list = [] for index in range(start, end + 1): left_subtrees = construct_bst(start, index - 1) right_subtrees = construct_bst(index + 1, end) for left in left_subtrees: for right in right_subtrees: root = Node(index) root.left = left root.right = right return_list.append(root) return return_list
def height_balanced(node: Node) -> Tuple[bool, int]: if node is None: return True, 0 if node.left is None and node.right is None: return True, 1 is_balanced_left, height_left = height_balanced(node.left) if not is_balanced_left: return is_balanced_left, height_left is_balanced_right, height_right = height_balanced(node.right) if not is_balanced_right or abs(height_right - height_left) > 1: return False, max(height_right, height_left) return True, max(height_right, height_left) + 1 if __name__ == "__main__": root = Node(1) root.left = Node(2) root.right = Node(3) root.left.left = Node(4) root.left.right = Node(5) root.left.right.right = Node(7) root.right.left = Node(6) assert height_balanced(root)[0] is True
if size_left >= size_right: return left_bst, False, size_left return right_bst, False, size_right def largest_bst( root_node: Optional[Node] = None) -> Tuple[Optional[Node], int]: bst_node, is_bst, size = _largest_bst(-sys.maxsize, sys.maxsize, root_node) return bst_node, size if __name__ == "__main__": root = Node(5) root.left = Node(2) root.right = Node(4) root.left.left = Node(1) root.left.right = Node(3) response = largest_bst(root) assert response[0].data == 2 assert response[1] == 3 root = Node(50) root.left = Node(30) root.right = Node(60) root.left.left = Node(5) root.left.right = Node(20) root.right.left = Node(45) root.right.right = Node(70)
a / \ c b \ / \ f e d """ from typing import Optional from daily_problems.binary_tree_node import Node, inorder_traversal def invert_tree(root_node: Optional[Node] = None) -> Optional[Node]: if root_node: root_node.left, root_node.right = root_node.right, root_node.left invert_tree(root_node.right) invert_tree(root_node.left) return root_node if __name__ == "__main__": root = Node("a") root.left = Node("b") root.right = Node("c") root.left.left = Node("d") root.left.right = Node("e") root.right.left = Node("f") print("inorder traversal") inorder_traversal(root) print("inorder traversal of inverted tree") inorder_traversal(invert_tree(root))
if root_node is None: return None left_node = binary_tree_to_full_binary_tree(root_node.left) right_node = binary_tree_to_full_binary_tree(root_node.right) if left_node is not None and right_node is None: return left_node elif right_node is not None and left_node is None: return right_node root_node.left = left_node root_node.right = right_node return root_node if __name__ == "__main__": root = Node(0) root.left = Node(1) root.left.left = Node(3) root.left.left.right = Node(5) root.right = Node(2) root.right.right = Node(4) root.right.right.left = Node(6) root.right.right.right = Node(7) print("original tree traversal") inorder_traversal(root) print("full tree traversal") inorder_traversal(binary_tree_to_full_binary_tree(root))
5 5 \ \ 2 1 / \ -1 2 """ from typing import Optional from daily_problems.binary_tree_node import Node def min_sum_path_root_to_leaf(root: Optional[Node]) -> int: if not root: return 0 if root.left is None and root.right is None: return root.data return root.data + min(min_sum_path_root_to_leaf(root.left), min_sum_path_root_to_leaf(root.right)) if __name__ == "__main__": tree = Node(10) tree.left = Node(5) tree.right = Node(5) tree.left.right = Node(2) tree.right.right = Node(1) tree.right.right.left = Node(-1) tree.right.right.right = Node(2) assert min_sum_path_root_to_leaf(tree) == 15
if root_node is None: return None if root_node.left is None and root_node.right is None: return None if root_node.right is None: largest = root_node.data parent = None else: parent = root_node largest, parent = get_largest_child(root_node.right, parent) if largest.left: return get_largest_child(largest.left, parent)[0].data else: # parent node return parent.data if __name__ == "__main__": root = Node(5) root.left = Node(3) root.right = Node(7) root.left.left = Node(1) root.left.right = Node(4) root.right.left = Node(6) root.right.right = Node(8) assert get_second_largest(root) == 7 assert get_second_largest_alt(root) == 7
""" from typing import Optional from daily_problems.binary_tree_node import Node from gfg.trees.tree_traversal import inorder def prune(node: Optional[Node]) -> Optional[Node]: if not node: return None node.left = prune(node.left) node.right = prune(node.right) if node.data == 1 or node.left or node.right: return node return None if __name__ == "__main__": tree = Node(0) tree.left = Node(1) tree.right = Node(0) tree.right.left = Node(1) tree.right.left.left = Node(0) tree.right.left.right = Node(0) tree = prune(tree) inorder(tree)
from daily_problems.binary_tree_node import Node def bin_tree_path(root_node: Optional[Node]) -> List[List[int]]: if not root_node: return [[]] if root_node.left is None and root_node.right is None: return [[root_node.data]] return_list = [] if root_node.left: for path in bin_tree_path(root_node.left): return_list.append([root_node.data] + path) if root_node.right: for path in bin_tree_path(root_node.right): return_list.append([root_node.data] + path) return return_list if __name__ == "__main__": tree = Node(1) tree.left = Node(2) tree.right = Node(3) tree.right.left = Node(4) tree.right.right = Node(5) print(bin_tree_path(tree))
def arithmetic_bin_tree(root_node: Optional[Node]) -> Union[int, float]: """ Assuming everything is good. There are no corner cases Using Inorder tree traversal for calculation Time Complexity: O(n) Space Complexity: O(n) # stack """ if not root_node: return 0 left_num: Union[int, float] = arithmetic_bin_tree(root_node.left) if left_num: symbol = sign_dict[root_node.data] right_num: Union[int, float] = arithmetic_bin_tree(root_node.right) return symbol(left_num, right_num) return int(root_node.data) if __name__ == "__main__": root = Node("*") root.left = Node("+") root.right = Node("+") root.left.left = Node(3) root.left.right = Node(2) root.right.left = Node(4) root.right.right = Node(5) assert arithmetic_bin_tree(root) == 45
return str(root.data) + preorder(root.left) + preorder(root.right) first_inorder = inorder(root_node_1) first_preorder = preorder(root_node_1) second_inorder = inorder(root_node_2) second_preorder = preorder(root_node_2) return first_inorder.find(second_inorder) > -1 and first_preorder.find( second_preorder) > -1 if __name__ == "__main__": first = Node(26) first.right = Node(3) first.right.right = Node(3) first.left = Node(10) first.left.left = Node(4) first.left.left.right = Node(30) first.left.right = Node(6) second = Node(10) second.right = Node(6) second.left = Node(4) second.left.right = Node(30) assert is_subtree_naive(first, second) is True assert is_subtree_fast(first, second) is True third = Node(10) third.left = Node(6) third.right = Node(4) third.left.right = Node(30)