示例#1
0
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}")
示例#2
0
    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)
示例#3
0
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)}")
示例#4
0
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)}")
示例#5
0
    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)
示例#6
0
    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)}")
示例#7
0
    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}")
示例#8
0
    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)