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
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
return 0, 0 left_sum_tree, left_sum_node = 0, 0 right_sum_tree, right_sum_node = 0, 0 if root_node.left: left_sum_tree, left_sum_node = _max_sum_path(root_node.left) if root_node.right: right_sum_tree, right_sum_node = _max_sum_path(root_node.right) return ( left_sum_node + right_sum_node + root_node.data, root_node.data + max(left_sum_tree, right_sum_tree), ) def max_sum_path(root_node: Optional[Node] = None) -> int: return max(*_max_sum_path(root_node)) if __name__ == "__main__": root = Node(10) root.left = Node(2) root.right = Node(10) root.left.left = Node(20) root.left.right = Node(1) root.right.right = Node(-25) root.right.right.left = Node(3) root.right.right.right = Node(4) assert max_sum_path(root) == 42
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
if root_node.left is None and root_node.right is None: count[root_node.data] += 1 return count, root_node.data count, left_sum = _subtree_sum(root_node.left, count) count, right_sum = _subtree_sum(root_node.right, count) total = left_sum + right_sum + root_node.data count[total] += 1 return count, total def subtree_sum(root_node: Node) -> int: count, _ = _subtree_sum(root_node, defaultdict(int)) max_occ = 0 return_val = 0 for key, value in count.items(): if value > max_occ: return_val = key max_occ = value return return_val if __name__ == "__main__": root = Node(5) root.left = Node(2) root.right = Node(-5) assert subtree_sum(root) == 2
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))
""" time complexity: O(n) space complexity: O(n) # stack """ if root_node is None: return 0, True count_left, is_left_unival = count_unival(root_node.left) count_right, is_right_unival = count_unival(root_node.right) total_count = count_left + count_right if is_left_unival and is_right_unival: if (root_node.left and root_node.data != root_node.left.data) or ( root_node.right and root_node.data != root_node.right.data ): return total_count, False return total_count + 1, True return total_count, False if __name__ == "__main__": root = Node(0) root.left = Node(1) root.right = Node(0) root.right.left = Node(1) root.right.right = Node(0) root.right.left.left = Node(1) root.right.left.right = Node(1) print(count_unival(root)[0])
def _is_bst(min_val: int, max_val: int, node: Optional[Node] = None) -> bool: if not node: return True if min_val < node.data < max_val: return _is_bst(min_val, node.data, node.left) and _is_bst( node.data, max_val, node.right) return False def is_bst(node: Optional[Node] = None) -> bool: return _is_bst(-sys.maxsize, sys.maxsize, node) if __name__ == "__main__": root = Node(4) root.left = Node(2) root.right = Node(5) root.left.left = Node(1) root.left.right = Node(3) assert is_bst(root) is True root = Node(3) root.left = Node(2) root.right = Node(5) root.right.left = Node(1) root.right.right = Node(4) assert is_bst(root) is False
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
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) root.right.right.left = Node(65)
""" 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)
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
return "" 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)