from utils.graphs import BiNode, ltbt from utils.treeviz import viz_tree def check_balanced(root: BiNode): return check_bal_rec(root) > 0 def check_bal_rec(node: BiNode): if not node: return 0 depth_right = check_bal_rec(node.right) depth_left = check_bal_rec(node.left) if depth_right < 0 or depth_left < 0: return -1 elif abs(depth_right - depth_left) > 1: return -1 else: return max(depth_right, depth_left) + 1 if __name__ == "__main__": extree = ltbt([0, 11, 12, 21, 222, 55, None, 31, 21, None, 42]) viz_tree(extree) resp = check_balanced(extree) print(f"Is tree balanced {resp}")
if left_res and left_has_anc: return (left_res, left_has_anc) right_res, right_has_anc = com_anc_helper(root.right, e1, e2) if right_res and right_has_anc: return (right_res, right_has_anc) # If both nodes found in the left and right trees # But not ancestors, this is the ancestor if left_res and right_res: return (root, True) else: if (root.val == e1 or root.val == e2): # Current is one of them and the other in subtrees is_anc = (left_res or right_res) return (root, is_anc) else: # Send up if one of target nodes found return (left_res if left_res else right_res, False) if __name__ == "__main__": ex = [2, 10, 30, 55, 15, None, None, 3, 37, None, 17] root = ltbt(ex) viz_tree(root) first_common_ancestor(root, 17, 37) first_common_ancestor(root, 17, 37) first_common_ancestor(root, 55, 3) first_common_ancestor(root, 3, 55) first_common_ancestor(root, 2, 9999)
from collections import defaultdict def paths_w_sum(root: BiNode, target: int) -> int: total_paths = 0 def find_paths_down(r, t, sofarsum, prev): nonlocal total_paths if not r: return sum_now = prev + r.val if sum_now - t in sofarsum: total_paths += sofarsum[sum_now - t] sofarsum[sum_now] += 1 find_paths_down(r.left, t, sofarsum, sum_now) find_paths_down(r.right, t, sofarsum, sum_now) sofarsum[sum_now] -= 1 find_paths_down(root, target, defaultdict(lambda: 0), 0) return total_paths if __name__ == "__main__": ex_tree = [10, 5, -3, 3, 2, 11, None, 3, -2, 1] root = ltbt(ex_tree) viz_tree(root) target = 8 print(f"Paths to {target} are {paths_w_sum(root,target)}")
def maximum_perfect_tree(tree_root: BiNode): max_now = 0 def max_perf_tree_depth(root: BiNode) -> int: nonlocal max_now if not root: return 0 l_max = max_perf_tree_depth(root.left) r_max = max_perf_tree_depth(root.right) val_now = 1 + min(l_max, r_max) if val_now > max_now: max_now = val_now return val_now max_perf_tree_depth(tree_root) return 2**max_now - 1 if __name__ == "__main__": tree_arr = [1] +\ [2, 3] + \ [None, 4] + [5, 6] +\ [None, None] + [None, None] + [7, 8] + [9, 10] [None] * 14 + [11] example_root = ltbt(tree_arr) print(f"Max tree is {maximum_perfect_tree(example_root)}")
ans = [] q.append((root, 0)) last_elem = None last_seen_level = 1 while q: ce, lvl = q.pop(0) if lvl != last_seen_level: ans.append(Node(ce.val)) last_seen_level = lvl last_elem = ans[lvl] else: last_elem.next = Node(ce.val) last_elem = last_elem.next for child in (ce.left, ce.right): if child is not None: q.append((child, lvl + 1)) return ans if __name__ == "__main__": extree = ltbt(list(range(10))) resp = tree2LinkedList(extree) for ll in resp: print(ll)
if (not root1) and (not root2): return True elif (not root1) or (not root2): return False else: if root1.val != root2.val: return False else: return check_same_tree(root1.left, root2.left) \ and check_same_tree(root1.right, root2.right) def check_sub_tree(t1: BiNode, t2: BiNode) -> bool: if not t1: return False if t1.val == t2.val: return check_same_tree(t1, t2) else: return check_sub_tree(t1.left, t2) or check_sub_tree(t1.right, t2) if __name__ == "__main__": tree1_list = [0, 10, 15, 20, 30, 25, 35] + [None] * 5 + [45] tree2_list = [10, 20, 30] t1 = ltbt(tree1_list) t2 = ltbt(tree2_list) print(f"Is t2 a subtree of t1 ? {check_sub_tree(t1,t2)}") print(f"Is t1 a subtree of t2 ? {check_sub_tree(t2,t1)}")
if n is None: return (None, None) else: range_l = get_tree_range(n.left) range_r = get_tree_range(n.right) if range_l[0] is False or range_r[0] is False: return (False, False) if check_bst_condition(n.val, range_l[1], range_r[0]): range_min = min(range_l[0], n.val) \ if range_l[0] is not None else n.val range_max = max(range_r[1], n.val) \ if range_r[1] is not None else n.val return (range_min, range_max) else: return (False, False) def check_bst_condition(val, max_left, min_right): return (not max_left or max_left <= val) \ and (not min_right or val < min_right) if __name__ == "__main__": extree = ltbt([100, 50, 150, 25, 99, None, 300] + [None] * 6 + [175, 301]) print(extree) viz_tree(extree) resp = check_bst(extree) print(f"Is tree a binary search tree ? {resp}")
node_id, node_val = get_node_for_graph(root) graf.node(node_id, node_val) while q: now_node = q.pop(0) now_node_id, _ = get_node_for_graph(now_node) for node in (now_node.left, now_node.right): if node is not None: node_id, node_val = get_node_for_graph(node) graf.node(node_id, node_val) graf.edge(now_node_id, node_id) q.append(node) graf.render(filename='graph_out/result.dot') def get_node_for_graph(node): node_id = str(id(node)) node_val = str(node.val) return node_id, node_val if __name__ == "__main__": test_arr = list(range(10)) root = ltbt(test_arr) print(root) viz_tree(root)