def insertIntoMaxTree(self, root: TreeNode, val: int) -> TreeNode:
     if root is None or root is not None and root.val < val:
         node = TreeNode(val)
         node.left = root
         return node
     root.right = self.insertIntoMaxTree(root.right, val)
     return root
def make_example_1():
    root = TreeNode(1)
    root.left = TreeNode(2)
    root.right = TreeNode(2)
    root.left.left = TreeNode(3)
    root.left.right = TreeNode(4)
    root.right.left = TreeNode(4)
    root.right.right = TreeNode(3)
    return root
 def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
     if nums:
         nums_left, middle, nums_right = nums[:len(nums) //
                                              2], nums[len(nums) //
                                                       2], nums[len(nums) //
                                                                2 + 1:]
         tree = TreeNode(middle)
         tree.left = self.sortedArrayToBST(nums_left)
         tree.right = self.sortedArrayToBST(nums_right)
         return tree
Пример #4
0
 def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
     length = len(nums)
     if length == 0:
         return None
     else:
         idx = length // 2
         node = TreeNode(nums[idx])
         node.left = self.sortedArrayToBST(nums[:idx])
         node.right = self.sortedArrayToBST(nums[idx + 1:])
         return node
Пример #5
0
 def generate_tree_with_range(start, end):
     if start > end:
         return [None]
     result = []
     for index in range(start, end + 1):
         for left_tree in generate_tree_with_range(start, index - 1):
             for right_tree in generate_tree_with_range(index + 1, end):
                 this_node = TreeNode(index)
                 this_node.left, this_node.right = left_tree, right_tree
                 result.append(this_node)
     return result
 def construct_tree(nums, left, right):
     if left >= right:
         return None
     max_i = left
     for index in range(left + 1, right):
         if nums[index] > nums[max_i]:
             max_i = index
     node = TreeNode(nums[max_i])
     node.left = construct_tree(nums, left, max_i)
     node.right = construct_tree(nums, max_i + 1, right)
     return node
def make_example():
    root = TreeNode(3)
    root.left = TreeNode(9)
    root.right = TreeNode(20)
    root.left.left = TreeNode(3)
    root.right.left = TreeNode(15)
    root.right.right = TreeNode(7)
    return root
 def sortedArrayToBST(self, num):
     if not num:
         return None
     
     if len(num) % 2 == 0:
         mid = len(num)/2 - 1
     else:
         mid = (len(num)+1)/2 - 1
     root = TreeNode(num[mid])
     root.left = self.sortedArrayToBST(num[:mid])
     root.right = self.sortedArrayToBST(num[mid+1:])
     return root
 def sortedArrayToBST(self, nums):
     """
     :type nums: List[int]
     :rtype: TreeNode
     """
     if nums is None or len(nums) == 0:
         return None
     mid_index = len(nums) >> 1
     node = TreeNode(nums[mid_index])
     node.left = self.sortedArrayToBST(nums[:mid_index])
     node.right = self.sortedArrayToBST(nums[mid_index + 1:])
     return node
Пример #10
0
def make_example_2():
    root = TreeNode(5)
    root.left = TreeNode(1)
    root.right = TreeNode(4)
    root.right.left = TreeNode(3)
    root.right.right = TreeNode(6)
    return root
Пример #11
0
    def deserialize(self, data):
        """Decodes your encoded data to tree.

        :type data: str
        :rtype: TreeNode
        """
        if data == "[]":
            return None
        values = list(map(lambda x: x.strip(), data[1:-1].split(',')))
        root = None
        q = Queue()

        for value in values:
            if value == "null":
                current = None
            else:
                current = TreeNode(int(value))
            if q.empty():
                root = current
            else:
                parent, direction = q.get()
                if not direction:
                    parent.left = current
                else:
                    parent.right = current
            if current is not None:
                q.put((current, 0))
                q.put((current, 1))
        return root
Пример #12
0
    def copy_from_iterable(self, iterable):
        """
        Copies data from iterable, which are put into the binary tree in level order

        Args:
            iterable (iterable): iterable object from which contents are copied and put into binary tree

        Returns:
            root node of the binary tree
        """

        # initialize root node
        self._root = TreeNode(iterable[0], 0)
        iterable_size = len(iterable)

        # create a list of tree nodes with each saving data from iterable
        # but topoligical relation has not been established yet
        # note that nodes saved in iterable are mapped to binary tree node in level order
        node_queue = [self._root]
        for i, data in enumerate(iterable[1:]):
            inserting_right = i & 1
            node_queue.append(
                TreeNode(data, -1 if inserting_right else 1) if data else None)

        i = 1
        while i < iterable_size:

            current_node = node_queue[i]

            if current_node is not None:
                # inserting_left == 1 when inserting a left child node
                # inserting_left == 0 when inserting a right child node
                inserting_left = i & 1
                # if a tree node has an indice i (0-indexed) in list, the parent node indice will be (i + 1) // 2 - 1 (0-indexed)
                current_parent_node = node_queue[(i + 1) // 2 - 1]
                if inserting_left:
                    current_parent_node.insert_left_child(current_node)
                else:
                    current_parent_node.insert_right_child(current_node)

            i += 1

        self._depth = self._root.height()
        self._size = self._root.size()

        return self._root
Пример #13
0
 def sortedListToBST(self, head: ListNode) -> TreeNode:
     if not head:
         return None
     elif not head.next:
         return TreeNode(head.val)
     else:
         slow = fast = head
         pre = None
         while fast and fast.next:
             pre = slow
             slow = slow.next
             fast = fast.next.next
         node = TreeNode(slow.val)
         pre.next = None
         node.left = self.sortedListToBST(head)
         node.right = self.sortedListToBST(slow.next)
         return node
Пример #14
0
    def buildTree(self, inorder, postorder):
        """
        :type inorder: List[int]
        :type postorder: List[int]
        :rtype: TreeNode
        """
        def find(l, v):
            for index, ele in enumerate(l):
                if ele == v:
                    return index
            return -1

        if len(postorder) == 0 or len(inorder) == 0:
            return None
        node = TreeNode(postorder[-1])
        index = find(inorder, postorder[-1])
        node.left = self.buildTree(inorder[:index], postorder[:index])
        node.right = self.buildTree(inorder[index + 1:], postorder[index:-1])
        return node
Пример #15
0
def binary_tree(array: List) -> Union[TreeNode, None]:
    """return the binary tree represented in array using preorder traversal order. For example [1, 2, 4, None, None, 5, None, None, 3, None, None] returns the following tree:
         1
        / \
       2   3
      / \
     4   5
    Args:
        array (List, optional): array representation of the output binary tree. Defaults to [].

    Returns:
        Union[TreeNode, None]: root node of the binary tree.
    """

    if len(array) == 0:
        return None
    root = TreeNode(val=array[0])
    path = [root]
    goLeft = [True]
    for x in array[1:]:
        currentNode = path[-1]
        if x is None:
            if goLeft[-1]:
                goLeft[-1] = False
            else:
                goLeft.pop()
                path.pop()
                while ((len(path) > 0) and (not goLeft[-1])
                       and (path[-1].right is not None)):
                    goLeft.pop()
                    path.pop()
        else:
            if goLeft[-1]:
                currentNode.left = TreeNode(val=x)
                path.append(currentNode.left)
                goLeft[-1] = False
                goLeft.append(True)
            else:
                currentNode.right = TreeNode(val=x)
                path.append(currentNode.right)
                goLeft.append(True)
    return root
Пример #16
0
 def flatten(self, root: TreeNode) -> None:
     """
     Do not return anything, modify root in-place instead.
     """
     if root:
         stack = [root]
         dummy = TreeNode(None)
         cur = dummy
         while stack:
             node = stack.pop()
             cur.right = node
             cur = node
             for c in (node.right, node.left):
                 if c:
                     stack.append(c)
             cur.left = None
Пример #17
0
    def test_insert_root(self):
        """
        Tests inserting new root node
        """

        new_root = TreeNode(-1, 0)
        self.binary_tree.insert_root(new_root)

        self.assertEqual(7, self.binary_tree.size())
        self.assertEqual(4, self.binary_tree.depth())
        self.assertEqual(-1, self.binary_tree.root().data())

        self.assertEqual([(-1, 4, 0), (0, 3, 1), None, (1, 2, 2),
                          (2, 2, 2), None, None, None, (4, 1, 3), None,
                          (6, 1, 3), None, None, None, None, None, None,
                          (7, 0, 4)],
                         self.binary_tree._level_order_traversal())
Пример #18
0
    def build_tree(self, input_data):
        n = len(input_data)
        if n == 0: return None
        self.list_node = []

        for data in input_data:
            if data:
                self.list_node.append(TreeNode(data))
            else:
                self.list_node.append(None)
        child_index = 1
        for i in range(n):
            if self.list_node[i] != None:
                try:
                    self.list_node[i].left = self.list_node[child_index]
                    child_index += 1
                    self.list_node[i].right = self.list_node[child_index]
                    child_index += 1
                except:
                    break
        return self.list_node[0]
Пример #19
0
class BinaryTree(object):
    def __init__(self, root=None):
        """
        Constructor

        Args:
            root (TreeNode): root node
        """
        self._root = root

        self._depth, self._size = 0, 0

        if root is not None:
            # if non-trival root node is given
            # maintain tree depth and size
            self._depth = root.height()
            self._size = root.size()

    def size(self):
        """
        Returns size
        """
        return self._size

    def depth(self):
        """
        Returns depth
        """
        return self._depth

    def copy_from_iterable(self, iterable):
        """
        Copies data from iterable, which are put into the binary tree in level order

        Args:
            iterable (iterable): iterable object from which contents are copied and put into binary tree

        Returns:
            root node of the binary tree
        """

        # initialize root node
        self._root = TreeNode(iterable[0], 0)
        iterable_size = len(iterable)

        # create a list of tree nodes with each saving data from iterable
        # but topoligical relation has not been established yet
        # note that nodes saved in iterable are mapped to binary tree node in level order
        node_queue = [self._root]
        for i, data in enumerate(iterable[1:]):
            inserting_right = i & 1
            node_queue.append(
                TreeNode(data, -1 if inserting_right else 1) if data else None)

        i = 1
        while i < iterable_size:

            current_node = node_queue[i]

            if current_node is not None:
                # inserting_left == 1 when inserting a left child node
                # inserting_left == 0 when inserting a right child node
                inserting_left = i & 1
                # if a tree node has an indice i (0-indexed) in list, the parent node indice will be (i + 1) // 2 - 1 (0-indexed)
                current_parent_node = node_queue[(i + 1) // 2 - 1]
                if inserting_left:
                    current_parent_node.insert_left_child(current_node)
                else:
                    current_parent_node.insert_right_child(current_node)

            i += 1

        self._depth = self._root.height()
        self._size = self._root.size()

        return self._root

    def is_full_binary_tree(self):
        """
        Returns if the binary tree is a full binary tree
        """
        return self._size == 2**(self._depth + 1) - 1

    def root(self):
        """
        Returns root node of the binary tree
        """
        return self._root

    def empty(self):
        """
        Returns if the binary tree is empty
        """
        return self._size == 0

    def insert_root(self, new_root):
        """
        Inserts a new root node to the binary tree

        Args:
            new_root (TreeNode): new root node to be inserted
        """

        # check if the given new root node is valid
        if new_root.is_root():
            # if given new root node already has left(right) child,
            # insert the binary tree as right(left) child
            if not new_root.has_left_child():
                new_root.insert_left_child(self.root())
            elif not new_root.has_right_child():
                new_root.insert_right_child(self.root())
            else:
                raise ValueError('the given root node has child node')

        # update root, size and depth
        self._root = new_root
        self._size = new_root.size()
        self._depth = new_root.height()

    def insert_left_subtree(self, left_subtree_root, left_subtree):
        """
        Inserts given binary tree (including it's root) to given tree node as left child

        Args:
            left_subtree_root (TreeNode): insert given binary tree to this tree node
            left_subtree (BinaryTree): insert this binary tree to given tree node as left child
        """

        left_subtree_root.insert_left_child(left_subtree.root())

        self._size = self._root.size()
        self._depth = self._root.height()

    def insert_right_subtree(self, right_subtree_root, right_subtree):
        """
        Inserts given binary tree (including it's root) to given tree node as right child

        Args:
            right_subtree_root (TreeNode): insert given binary tree to this tree node
            right_subtree (BinaryTree): insert this binary tree to given tree node as right child
        """

        right_subtree_root.insert_right_child(right_subtree.root())

        self._size = self._root.size()
        self._depth = self._root.height()

    def get_lowest_leaf(self, starting_node=None):
        """
        Gets lowest leaf node below given starting node

        If starting node is given, it's equivalent to fetch the lowest leaf in subtree rooted at starting node. 

        Args:
            starting_node (TreeNode): the tree node below which the lowest leaf is retrieved
        """

        # default to root node
        if starting_node is None:
            starting_node = self._root

        lowest_leaf = starting_node
        stack = [starting_node]

        while len(stack):
            node = stack.pop()

            # if a lower node is found, update the lowest leaf
            if node.height() < lowest_leaf.height():
                lowest_leaf = node

            if node.has_left_child():
                stack.append(node.left_child())
            if node.has_right_child():
                stack.append(node.right_child())

        return lowest_leaf

    def remove_subtree(self, subtree_root):
        """
        Removes subtree from current binary tree

        Args:
            subtree_root (TreeNode): root node of subtree to be removed
        """

        # remove all descendant nodes below the subtree root node
        subtree_root.clear_descendant()
        # get the parent node of subtree root in original binary tree
        subtree_root_parent = subtree_root.parent()

        if subtree_root_parent is None:
            self.__init__(root=None)
            return

        # reset the child node of the parent node of subtree root
        if subtree_root.is_left_child():
            subtree_root_parent._left_child = None
        else:
            subtree_root_parent._right_child = None
        # release memory
        del subtree_root

        # since the structure changes for the subtree rooted at subtree_root_parent,
        # update height/size of each node in this specific subtree
        lowest_leaf = self.get_lowest_leaf(subtree_root_parent)
        lowest_leaf.update_height_from_child()
        lowest_leaf.update_ancestor_height()

        subtree_root_parent.update_size()
        subtree_root_parent.update_ancestor_size()

        self._size = self._root.size()
        self._depth = self._root.height()

    def split_subtree(self, subtree_root):
        """
        Splits the subtree rooted at given node from the binary tree

        Args:
            subtree_root (TreeNode): root node of subtree to be splitted
        """

        # remove all descendant nodes below the subtree root node
        new_leaf_node = subtree_root.parent()
        # make subtree_root a root node
        subtree_root._parent = None

        # reset the child node of the parent node of subtree root
        if subtree_root.is_left_child():
            new_leaf_node._left_child = None
        else:
            new_leaf_node._right_child = None

        new_leaf_node.update_size()
        new_leaf_node.update_ancestor_size()

        # update the tree left after the split
        lowest_leaf = self.get_lowest_leaf(new_leaf_node)
        lowest_leaf.update_height_from_child()
        lowest_leaf.update_ancestor_height()

        self._size = self._root.size()
        self._depth = self._root.height()

        # update depth/height of each node in splitted subtree
        subtree_root._node_type = 0
        subtree_root.update_depth()
        subtree_root.update_descendant_depth()

        lowest_leaf = self.get_lowest_leaf(subtree_root)
        lowest_leaf.update_height_from_child()
        lowest_leaf.update_ancestor_height()

        return subtree_root

    def preorder_traversal(self, starting_node=None):
        """
        Traverse the binary tree in pre-order: parent node -> left child -> right child

        Args:
            starting_node (TreeNode): traverse the subtree rooted at given starting node

        Returns:
            data_array (list): list of data saved in binary tree
        """
        data_array = []

        if starting_node is None:
            starting_node = self._root

        stack = Stack()
        current_node = starting_node

        while True:

            while current_node is not None:
                data_array.append(current_node.data())
                # push right child node into stack if it exists
                stack.push(current_node.right_child())
                # always go along left child
                current_node = current_node.left_child()

            if stack.empty():
                break

            current_node = stack.pop()

        return data_array

    def inorder_traversal(self, starting_node=None):
        """
        Traverse the binary tree in in-order: left child -> parent node -> right child

        Args:
            starting_node (TreeNode): traverse the subtree rooted at given starting node

        Returns:
            data_array (list): list of data saved in binary tree
        """
        data_array = []

        if starting_node is None:
            starting_node = self._root

        stack = Stack()
        current_node = starting_node

        while True:

            while current_node is not None:
                stack.push(current_node)
                # always go along left child
                current_node = current_node.left_child()

            if stack.empty():
                break

            current_node = stack.pop()
            data_array.append(current_node.data())
            current_node = current_node.right_child()

        return data_array

    def _to_highest_leftmost_leaf(self, node_stack):
        """
        Goes to the highest leftmost leaf node visible from left while adding node on path to given stack

        Args:
            node_stack (Stack): containing nodes traveled when going to the highest leftmost leaf node visible from left
        """
        top_node = node_stack.top()

        while top_node is not None:
            # in order to get leftmost leaf, always check left subtree first
            if top_node.has_left_child():
                if top_node.has_right_child():
                    node_stack.push(top_node.right_child())
                node_stack.push(top_node.left_child())
            else:
                # only if no left subtree available
                node_stack.push(top_node.right_child())
            top_node = node_stack.top()

        node_stack.pop()

    def postorder_traversal(self, starting_node=None):
        """
        Traverses the binary tree in post-order: left child -> right child -> parent node

        Args:
            starting_node (TreeNode): traverse the subtree rooted at given starting node

        Returns:
            data_array (list): list of data saved in binary tree
        """
        data_array = []

        if self._root is None:
            return data_array

        if starting_node is None:
            starting_node = self._root

        stack = Stack()
        current_node = starting_node
        stack.push(current_node)

        while not stack.empty():
            top_node = stack.top()
            if top_node != current_node.parent():
                self._to_highest_leftmost_leaf(stack)
            current_node = stack.pop()
            data_array.append(current_node.data())

        return data_array

    def _level_order_traversal(self, starting_node=None, include_none=True):
        """
        Traverses the binary tree from top level to bottom and saves data/height/depth for testing purpose

        Args:
            starting_node (TreeNode): traverse the subtree rooted at given starting node
            include_none (bool): True if including None node in binary tree

        Returns:
            data_array ([3-tuple]): [(data saved in node, height, depth)]
        """
        data_array = []

        # returns empty list if the binary tree is empty
        if self._root is None:
            return data_array

        # traverse from root if starting node is not given
        if starting_node is None:
            starting_node = self._root

        queue = Queue()
        # (data, height, depth, left child, right child)
        queue.enqueue((starting_node.data(), starting_node.height(),
                       starting_node.depth(), starting_node.left_child(),
                       starting_node.right_child()))

        while not queue.empty():
            top_node = queue.dequeue()

            if top_node[0] is not None:
                # if it's a non-trival node, append data/height/depth
                data_array.append((top_node[0], top_node[1], top_node[2]))
            else:
                data_array.append(None)

            # if the node is not on the deepest level, left and right child can be added into queue and visited soon
            if top_node[2] < self.depth():
                top_node_left_child, top_node_right_child = top_node[
                    3], top_node[4]

                entry = [None, top_node[1] - 1, top_node[2] + 1, None, None]
                if top_node_left_child is not None:
                    entry[0] = top_node_left_child.data()
                    entry[3] = top_node_left_child.left_child()
                    entry[4] = top_node_left_child.right_child()
                queue.enqueue(tuple(entry))

                entry = [None, top_node[1] - 1, top_node[2] + 1, None, None]
                if top_node_right_child is not None:
                    entry[0] = top_node_right_child.data()
                    entry[3] = top_node_right_child.left_child()
                    entry[4] = top_node_right_child.right_child()
                queue.enqueue(tuple(entry))

        # if include_none == False, filter out the None element
        if not include_none:
            data_array = list(filter(lambda x: x is not None, data_array))

        # remove all None at the end of list since they are trival and not informative
        while data_array[-1] is None:
            data_array.pop()

        return data_array

    def level_order_traversal(self, starting_node=None, include_none=True):
        """
        Traverses the binary tree from top level to bottom

        Args:
            starting_node (TreeNode): traverse the subtree rooted at given starting node
            include_none (bool): True if including None node in binary tree

        Returns:
            data_array ([object]): [data saved in node]
        """

        data_array = self._level_order_traversal(starting_node, include_none)

        if include_none:
            data_array = [
                data[0] if data is not None else None for data in data_array
            ]
        else:
            data_array = list(filter(lambda x: x is not None, data_array))
            data_array = [data[0] for data in data_array]

        return data_array
    # @param root, a tree node
    # @return an integer
    def maxDepth(self, root):
        if not bool(root):
            return 0
        if root.left == None:
            if root.right == None:
                return 1
            else:
                return 1 + self.maxDepth(root.right)
        elif root.right == None:
            if root.left == None:
                return 1
            else:
                return 1 + self.maxDepth(root.left)
        else:
            return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))


testRoot = TreeNode(5)
testRoot.left = TreeNode(3)
testRoot.right = TreeNode(8)
testRoot.left.left = TreeNode(2)
testRoot.left.right = TreeNode(4)
testRoot.right.left = TreeNode(7)
testRoot.right.left.left = TreeNode(6)

sol = Solution()
print sol.maxDepth(testRoot)
print sol.maxDepth({})
Пример #21
0
 def isValidBST(self, root: TreeNode) -> bool:
     if root:
         self.pre = TreeNode(-2**32)
         return self.postOrderTraverse(root)
     else:
         return True
Пример #22
0
    # @param q, a tree node
    # @return a boolean
    def isSameTree(self, p, q):
        if not bool(p):
            if not bool(q):
                return True
            else:
                return False
        if not bool(q):
            if not bool(p):
                return True
            else:
                return False
        if p.val == q.val:
            return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
        else:
            return False

sol = Solution()
print sol.isSameTree({}, {0})

pTree = TreeNode(2)
pTree.left = TreeNode(1)
pTree.right = TreeNode(3)

qTree = TreeNode(2)
qTree.left = TreeNode(1)
qTree.right = TreeNode(3)
print sol.isSameTree(pTree, qTree)
            
        
Пример #23
0
            sums.append(self.dfsSum(root.left, root.val))
        if root.right != None:
            sums.append(self.dfsSum(root.right, root.val))

        return sum(sums)

    def dfsSum(self, root, cursum):
        ret = []
        cursum = cursum * 10 + root.val
        if not root.left and not root.right:
            return cursum

        if root.left != None and root.right != None:
            return self.dfsSum(root.left, cursum) + self.dfsSum(root.right, cursum)

        if root.left != None and not root.right:
            return self.dfsSum(root.left, cursum)

        if root.right != None and not root.left:
            return self.dfsSum(root.right, cursum)


sol = Solution()
t = TreeNode(8)
t.left = TreeNode(3)
t.right = TreeNode(5)
t.left.right = TreeNode(9)
t.left.right.left = TreeNode(9)
t.left.right.right = TreeNode(5)
print sol.sumNumbers(t)