Beispiel #1
0
 def construct_bst_helper(left_bound: int,
                          right_bound: int) -> Optional[TreeNode]:
     if left_bound > right_bound:
         return None
     mid_point = (left_bound + right_bound) // 2
     root_node = TreeNode(values[mid_point])
     root_node.left = construct_bst_helper(left_bound, mid_point - 1)
     root_node.right = construct_bst_helper(mid_point + 1, right_bound)
     return root_node
    def reversed_pre_order_traversal(current_node: TreeNode) -> None:
        """
        :param current_node: flattening sub tree beneath current_node; current_node is not None
        """
        nonlocal previous_node
        if current_node.right:
            reversed_pre_order_traversal(current_node.right)
        if current_node.left:
            reversed_pre_order_traversal(current_node.left)

        current_node.right = previous_node
        current_node.left = None
        previous_node = current_node
Beispiel #3
0
        def _trim_boundary_helper(current_node: TreeNode) -> TreeNode:
            if not current_node:
                return current_node

            if current_node.val < low_val:
                # root and its left tree will be dropped
                return _trim_boundary_helper(current_node.right)
            elif current_node.val > high_val:
                # root and its right tree will be dropped
                return _trim_boundary_helper(current_node.left)

            current_node.left = _trim_boundary_helper(current_node.left)
            current_node.right = _trim_boundary_helper(current_node.right)
            return current_node
 def mark_parent(current_node: TreeNode,
                 parent_node: TreeNode = None) -> None:
     current_node.parent = parent_node
     if current_node.left:
         mark_parent(current_node.left, current_node)
     if current_node.right:
         mark_parent(current_node.right, current_node)
 def convert_bst_helper(current_node: TreeNode) -> None:
     nonlocal accumulator
     if current_node is not None:
         convert_bst_helper(current_node.right)
         accumulator += current_node.val
         current_node.val = accumulator
         convert_bst_helper(current_node.left)
Beispiel #6
0
 def build_bst(i: int, j: int) -> TreeNode:
     """
     :return: build binary search tree for in_order_list[i: j]
     """
     mid = (i + j) // 2
     return TreeNode(in_order_list[mid],
                     left=(build_bst(i, mid) if mid > i else None),
                     right=(build_bst(mid + 1, j) if mid + 1 < j else None))
Beispiel #7
0
 def construct_bst_helper(
         list_start: Optional[ListNode]) -> Optional[TreeNode]:
     if list_start is None:
         return None
     slow_ptr = list_start
     slow_before = None
     fast_ptr = list_start
     while fast_ptr.next and fast_ptr.next.next:
         slow_before = slow_ptr
         slow_ptr = slow_ptr.next
         fast_ptr = fast_ptr.next.next
     root_node = TreeNode(slow_ptr.val)
     if slow_before:
         slow_before.next = None
         root_node.left = construct_bst_helper(list_start)
     if slow_ptr.next:
         root_node.right = construct_bst_helper(slow_ptr.next)
     return root_node
 def add_merkle_hash_to(current_node: TreeNode) -> str:
     """
     :param current_node: add Merkle hash code to represent the sub tree beneath current_node
     :return: Merkle hash code of the sub tree beneath current_node
     """
     current_node.hash_code = get_sh256_hash((add_merkle_hash_to(current_node.left) if current_node.left else '#') +
                                             str(current_node.val) +
                                             (add_merkle_hash_to(current_node.right) if current_node.right else '#'))
     return current_node.hash_code
def test_build_tree(node_list: List[Optional[int]]) -> BinaryTree:
    if not node_list or node_list[0] is None:
        return BinaryTree(None)
    return_tree = BinaryTree(TreeNode(node_list[0]))
    node_queue = deque([return_tree.root])
    node_child_counter = 0
    current_node = None
    for i in range(1, len(node_list)):
        if node_child_counter == 0:
            current_node = node_queue.popleft()
        if node_list[i] is not None:
            if node_child_counter:
                current_node.right = TreeNode(node_list[i])
                node_queue.append(current_node.right)
            else:
                current_node.left = TreeNode(node_list[i])
                node_queue.append(current_node.left)
        node_child_counter = (node_child_counter + 1) % 2
    return return_tree
Beispiel #10
0
def invert_tree(root: TreeNode) -> Optional[TreeNode]:
    """
    :param root: root of a binary tree
    :return: root of the inverted binary tree, after flipping left and right child of each node
    """
    if root is None:
        return None
    right = invert_tree(root.right) if root.right else None
    left = invert_tree(root.left) if root.left else None
    root.left, root.right = right, left
    return root
def prune_tree_helper(current_root: TreeNode) -> bool:
    """
    Prune the subtree of current_root
    :param current_root: root node of current sub tree; guaranteed not equals to None
    :return: whether subtree of current_root contains 1
    """
    subtree_contains_1 = False

    if current_root.left:
        if prune_tree_helper(current_root.left):
            subtree_contains_1 = True
        else:
            current_root.left = None

    if current_root.right:
        if prune_tree_helper(current_root.right):
            subtree_contains_1 = True
        else:
            current_root.right = None

    return current_root.val == 1 or subtree_contains_1
def trim_BST(root: TreeNode, low_val: int, high_val: int) -> TreeNode:
    """
    Recursively remove all nodes whose values that are out of [low_val, high_val]

    :param root: root node of the original Binary Search Tree
    :param low_val: remove all nodes that are strictly less than low_val
    :param high_val: remove all nodes that are strictly greater than low_val
    :return: root of the updated Binary Search Tree
    """
    if not root:
        return root

    if root.val < low_val:
        # root and its left tree will be dropped
        return trim_BST(root.right, low_val, high_val)
    elif root.val > high_val:
        # root and its right tree will be dropped
        return trim_BST(root.left, low_val, high_val)

    root.left = trim_BST(root.left, low_val, high_val)
    root.right = trim_BST(root.right, low_val, high_val)
    return root
Beispiel #13
0
 def insert(self, v: TREE_NODE_TYPE) -> TREE_NODE_TYPE:
     """
     :param v: insert a TreeNode into the tree with value node.val = v so that the tree remains complete
     :return: the value of the parent of the inserted TreeNode;
     """
     parent_node = self.node_not_full[0]
     self.node_not_full.append(TreeNode(v))
     if not parent_node.left:
         parent_node.left = self.node_not_full[-1]
     else:
         parent_node.right = self.node_not_full[-1]
         self.node_not_full.pop(0)
     return parent_node.val
Beispiel #14
0
 def insert(self, value: TREE_NODE_TYPE) -> None:
     """
     :return: insert a new node of value into the BST
     """
     if self.root is None:
         self.root = TreeNode(value)
     else:
         current_node = self.root
         inserted = False
         while not inserted:
             if value < current_node.val:
                 if not current_node.left:
                     current_node.left = TreeNode(value)
                     inserted = True
                 else:
                     current_node = current_node.left
             else:
                 if not current_node.right:
                     current_node.right = TreeNode(value)
                     inserted = True
                 else:
                     current_node = current_node.right
def merge_trees(root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
    """
    :param root1: root of binary tree 1
    :param root2: root of binary tree 2
    :return: root of merged tree; returned tree may point to TreeNodes in root1 or root2
    """
    if root1 is None and root2 is None:
        return None

    if root1 is not None and root2 is not None:
        return TreeNode(root1.val + root2.val,
                        left=merge_trees(root1.left, root2.left) if root1.left or root2.left else None,
                        right=merge_trees(root1.right, root2.right) if root1.right or root2.right else None)
    else:
        return root1 if root1 else root2
Beispiel #16
0
def add_one_row(root: TreeNode, value: int, depth: int) -> TreeNode:
    """
    :param root: root of a proper binary tree
    :param value: add a new row at level depth with all nodes set to value
    :param depth: add a new row at level depth with all nodes set to value
    :return: root of the new binary tree
    """
    if depth == 1:
        return TreeNode(value, left=root)

    current_level = [root]
    current_depth = 1

    while current_depth < depth - 1:
        next_level = [node.left for node in current_level if node.left is not None]
        next_level.extend([node.right for node in current_level if node.right is not None])
        current_depth += 1
        current_level = next_level

    for node in current_level:
        node.left = TreeNode(value, left=node.left)
        node.right = TreeNode(value, right=node.right)

    return root
Beispiel #17
0

def invert_tree(root: TreeNode) -> Optional[TreeNode]:
    """
    :param root: root of a binary tree
    :return: root of the inverted binary tree, after flipping left and right child of each node
    """
    if root is None:
        return None
    right = invert_tree(root.right) if root.right else None
    left = invert_tree(root.left) if root.left else None
    root.left, root.right = right, left
    return root


node = TreeNode(4)
node.left = TreeNode(2)
node.left.left = TreeNode(1)
node.left.right = TreeNode(3)
node.right = TreeNode(7)
node.right.left = TreeNode(6)
node.right.right = TreeNode(9)

tree = BinaryTree(node)
assert tree.preorder_traversal() == [4, 2, 1, 3, 7, 6, 9]
assert tree.inorder_traversal() == [1, 2, 3, 4, 6, 7, 9]
assert tree.postorder_traversal() == [1, 3, 2, 6, 9, 7, 4]
assert tree.layer_traversal_by_layer() == [[4], [2, 7], [1, 3, 6, 9]]
assert tree.leetcode_traversal() == [
    4, 2, 7, 1, 3, 6, 9, None, None, None, None, None, None, None, None
]
Beispiel #18
0
    # print('Deleted: %d, Remaining: %s' % (values[i], str(deletion_tree.traversal())))
    assert deletion_tree.traversal() == values[:i] + values[i + 1:]

expected_values = [6, 7, 8, 9, 10, 11, 12, 13]
assert new_bst.traverse_range(6, 13) == expected_values
assert new_bst.traverse_range(6, 14) == expected_values
assert new_bst.traverse_range(5.5, 13) == expected_values

sorted_list = list(range(1, 11))
head = LinkedList.create_linked_list(sorted_list)
new_bst = BST(head)
assert new_bst.traversal() == sorted_list
assert new_bst.is_balanced()

new_bst = BST([-1])
new_bst.root.right = TreeNode(1)
new_bst.root.right.left = TreeNode(-1)
assert new_bst.is_valid()

new_bst = BST([1])
new_bst.root.left = TreeNode(-1)
new_bst.root.left.right = TreeNode(1)
assert not new_bst.is_valid()

new_bst = BST([1, 3, 4])
new_bst.root.left.right = TreeNode(2)
for i in range(1, 5):
    assert new_bst.kth_smallest_element(
        i) == i, "Expecting %d got %d" % (i, new_bst.kth_smallest_element(i))
assert new_bst.kth_smallest_element(5) is None