Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0

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
Exemple #5
0
    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)
Exemple #6
0
  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))
Exemple #7
0
    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))
Exemple #8
0
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
Exemple #9
0
    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))
Exemple #12
0
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)