Example #1
0
    def all_elements_in_two_binary_search_trees(self, root1: List[int],
                                                root2: List[int]) -> List[int]:
        root1 = TreeNode.deserialize(root1)
        root2 = TreeNode.deserialize(root2)

        def inorder(n):
            if n is None: return
            yield from inorder(n.left)
            yield n.val
            yield from inorder(n.right)

        def consume(g):
            try:
                return next(g)
            except StopIteration as e:
                return None

        def merge_values(root1, root2):
            g1, g2 = inorder(root1), inorder(root2)
            n1, n2 = consume(g1), consume(g2)
            while n1 is not None and n2 is not None:
                if n1 < n2:
                    yield n1
                    n1 = consume(g1)
                else:
                    yield n2
                    n2 = consume(g2)
            while n1 is not None:
                yield n1
                n1 = consume(g1)
            while n2 is not None:
                yield n2
                n2 = consume(g2)

        return list(merge_values(root1, root2))
    def binary_tree_level_order_traversal(self, root: typing.List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)
        if root is None: return None
        sent = prev = TreeNode(0)

        def inorder(node):
            nonlocal prev
            if node is None: return
            inorder(node.left)
            # process node
            prev.right = node
            node.left = prev
            prev = node
            inorder(node.right)

        inorder(root)
        head = sent.right
        head.left = prev
        prev.right = head
        return head


        # 1. Perform inorder traversal and create the doubly linked list on the fly
        # 2. To access prev node after dfs, set prev as nonlocal variable
        """
Example #3
0
 def dfs(l, r):
     if l > r: return None
     mid = (r - l) // 2 + l
     root = TreeNode(nums[mid])
     root.left = dfs(l, mid - 1)
     root.right = dfs(mid + 1, r)
     return root
 def dfs(pl, pr, il, ir):
     if pl > pr: return None
     n = TreeNode(preorder[pl])
     if pl == pr: return n
     mid = inord_map[n.val]
     n.left = dfs(pl + 1, pl + (mid - il), il, mid - 1)
     n.right = dfs(pl + (mid - il) + 1, pr, mid + 1, il)
     return n
 def dfs(pl, pr, il, ir):
     if pl > pr: return None
     node = TreeNode(postorder[pr])
     if pl == pr: return node
     inord_mid = inord_map[node.val]
     postord_mid = pr - (ir - inord_mid)
     node.left = dfs(pl, postord_mid - 1, il, inord_mid - 1)
     node.right = dfs(postord_mid, pr - 1, inord_mid + 1, ir)
     return node
    def inorder_successor_in_bst(self, root: List[int],
                                 p: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)
        p = TreeNode.deserialize(p)

        suc, t = None, root
        while t:
            if t.val <= p.val:
                t = t.right
            else:
                suc = t
                t = t.left
        return suc
Example #7
0
    def split_bst(self, root: List[int], V: int) -> List[List[int]]:
        root = TreeNode.deserialize(root)

        def preorder(node):
            if node is None: return (None, None)
            if node.val <= V:
                left, right = preorder(node.right)
                node.right = left
                return (node, right)
            else:
                left, right = preorder(node.left)
                node.left = right
                return (left, node)

        left, right = preorder(root)
        return [TreeNode.serialize(left), TreeNode.serialize(right)]
Example #8
0
    def recover_binary_search_tree(self, root: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)
        """
        Record first, second everytime first >= second
        """
        first = second = prev = None

        def inorder(n):
            nonlocal first, second, prev
            if n is None: return
            inorder(n.left)

            # 'prev is None' means root node can be included to first
            if not first and (prev is None or prev.val >= n.val):
                first = prev

            if first and prev and prev.val >= n.val:
                second = n

            prev = n
            inorder(n.right)

        inorder(root)

        first.val, second.val = second.val, first.val

        return root
Example #9
0
 def inorder(n):
     if n is None: return TreeNode(val)
     if val < n.val:
         n.left = inorder(n.left)
     else:
         n.right = inorder(n.right)
     return n
Example #10
0
    def lowest_common_ancestor_of_a_binary_search_tree(self, root: List[int],
                                                       p: int,
                                                       q: int) -> TreeNode:
        root = TreeNode.deserialize(root)

        def find_node(node, num):
            if not node: return None
            if node.val == num: return node
            l = find_node(node.left, num)
            r = find_node(node.right, num)
            return l or r

        p = find_node(root, p)
        q = find_node(root, q)

        # Actual code starts from here
        def find_lca(root):
            if root in (None, p, q): return root
            l = find_lca(root.left)
            r = find_lca(root.right)
            if l and r: return root
            return l or r

        n = find_lca(root)
        return n.val
    def inorder_successor_in_bst(self, root: List[int],
                                 p: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)
        p = TreeNode.deserialize(p)

        prev, successor = None, None

        def inorder(n):
            nonlocal prev, successor
            if n is None: return
            inorder(n.left)
            if prev is not None and prev.val == p.val:
                successor = n
            prev = n
            inorder(n.right)

        inorder(root)
        return successor
Example #12
0
 def insert_into_a_binary_search_tree(self, root: List[int],
                                      val: int) -> TreeNode:
     root = TreeNode.deserialize(root)
     new_node = TreeNode(val)
     if root is None: return new_node
     prev = None
     cur = root
     while cur is not None:
         prev = cur
         if val < cur.val:
             cur = cur.left
         else:
             cur = cur.right
     if prev.val > val:
         prev.left = new_node
     else:
         prev.right = new_node
     return root
    def inorder_successor_in_bst(self, root: List[int],
                                 p: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)
        p = TreeNode.deserialize(p)

        prev, s, t = None, [], root
        while s or t:
            while t:
                s.append(t)
                t = t.left

            t = s.pop()
            if prev and prev.val == p.val:
                return t

            prev = t
            t = t.right
        return None
Example #14
0
    def binary_tree_postorder_traversal(self, root: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)

        def postorder(n):
            if n is None: return
            yield from postorder(n.left)
            yield from postorder(n.right)
            yield n.val

        return list(postorder(root))
Example #15
0
    def binary_tree_inorder_traversal(
            self, root: typing.List[int]) -> typing.List[int]:
        root = TreeNode.deserialize(root)

        def inorder(n):
            if n is None: return
            yield from inorder(n.left)
            yield n.val
            yield from inorder(n.right)

        return list(inorder(root))
Example #16
0
    def merge_two_bsts(self, root1: List[int], root2: List[int]) -> TreeNode:
        root1 = TreeNode.deserialize(root1)
        root2 = TreeNode.deserialize(root2)

        a1, a2 = [], []

        def inorder(n, a):
            if n is None: return
            inorder(n.left, a)
            a.append(n)
            inorder(n.right, a)

        def merge(a1, a2):
            a = []
            l1, l2 = 0, 0
            while l1 < len(a1) and l2 < len(a2):
                if a1[l1].val < a2[l2].val:
                    a.append(a1[l1])
                    l1 += 1
                else:
                    a.append(a2[l2])
                    l2 += 1
            while l1 < len(a1):
                a.append(a1[l1])
                l1 += 1
            while l2 < len(a2):
                a.append(a2[l2])
                l2 += 1
            return a

        def bst(l, r, a):
            if l > r: return None
            mid = (r - l) // 2 + l
            n = a[mid]
            n.left = bst(l, mid - 1, a)
            n.right = bst(mid + 1, r, a)
            return n

        inorder(root1, a1)
        inorder(root2, a2)
        return bst(0, len(a1) + len(a2) - 1, merge(a1, a2))
Example #17
0
 def binary_tree_inorder_traversal(
         self, root: typing.List[int]) -> typing.List[int]:
     root = TreeNode.deserialize(root)
     s, t, res = [], root, []
     while s or t:
         while t:
             s.append(t)
             t = t.left
         t = s.pop()
         res.append(t.val)
         t = t.right
     return res
    def check_completeness_of_a_binary_tree(
            self, root: typing.List[int]) -> typing.List[int]:
        root = TreeNode.deserialize(root)

        if root is None: return True
        q = collections.deque([root])
        while q:
            n = q.popleft()
            if n is None: break
            q.append(n.left)
            q.append(n.right)
        return not any(q)
Example #19
0
    def binary_tree_postorder_traversal(self, root: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)

        res = []

        def postorder(n):
            if n is None: return
            postorder(n.left)
            postorder(n.right)
            res.append(n.val)

        postorder(root)
        return res
Example #20
0
    def insert_into_a_binary_search_tree(self, root: List[int],
                                         val: int) -> TreeNode:
        root = TreeNode.deserialize(root)

        def inorder(n):
            if n is None: return TreeNode(val)
            if val < n.val:
                n.left = inorder(n.left)
            else:
                n.right = inorder(n.right)
            return n

        return inorder(root)
Example #21
0
    def binary_tree_inorder_traversal(
            self, root: typing.List[int]) -> typing.List[int]:
        root = TreeNode.deserialize(root)
        res = []

        def inorder(n):
            if n is None: return
            inorder(n.left)
            res.append(n.val)
            inorder(n.right)

        inorder(root)
        return res
Example #22
0
    def binary_tree_postorder_traversal(self, root: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)

        if not root: return []
        s, s1 = [root], []
        while s:
            n = s.pop()
            s1.append(n)
            if n.left is not None:
                s.append(n.left)
            if n.right is not None:
                s.append(n.right)

        return [n.val for n in reversed(s1)]
Example #23
0
 def binary_tree_level_order_traversal(self,
                                       root: typing.List[int]) -> TreeNode:
     root = TreeNode.deserialize(root)
     if root is None: return []
     q = collections.deque([(0, root)])
     result = []
     while q:
         l, node = q.popleft()
         while len(result) <= l:
             result.append([])
         result[l].append(node.val)
         if node.left: q.append((l + 1, node.left))
         if node.right: q.append((l + 1, node.right))
     return result
Example #24
0
    def single_value_tree(self, root: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)

        c = 0

        def postord(t):
            nonlocal c
            if t is None: return set()
            total = postord(t.left) | postord(t.right) | set([t.val])
            if len(total) == 1:
                c += 1
            return total

        postord(root)
        return c
Example #25
0
    def upside_down(self, root: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)

        if not root: return None

        def upside_down(n):
            if n.left == n.right == None:
                return n
            new_root = upside_down(n.left)
            n.left.right = n
            n.left.left = n.right
            n.right = n.left = None
            return new_root

        return upside_down(root)
Example #26
0
 def binary_tree_level_order_traversal(self,
                                       root: typing.List[int]) -> TreeNode:
     root = TreeNode.deserialize(root)
     if not root: return []
     q = collections.deque([root])
     result = []
     while q:
         l = len(q)
         temp = []
         for i in range(l):
             node = q.popleft()
             temp.append(node.val)
             if node.left is not None: q.append(node.left)
             if node.right is not None: q.append(node.right)
         result.append(temp)
     return result
    def binary_tree_paths(self, root: List[int]) -> List[str]:
        root = TreeNode.deserialize(root)

        def preorder(n, slate):
            if n is None:
                return
            slate.append(n.val)
            if n.left == n.right == None:
                res.append('->'.join(map(str, slate)))
            else:
                preorder(n.left, slate)
                preorder(n.right, slate)
            slate.pop()

        res = []
        preorder(root, [])
        return res
Example #28
0
    def binary_tree_preorder_traversal(
            self, root: typing.List[int]) -> typing.List[int]:
        root = TreeNode.deserialize(root)

        if not root: return []

        def preorder(root):
            s = [root]
            while s:
                n = s.pop()
                yield n.val
                if n.right is not None:
                    s.append(n.right)
                if n.left is not None:
                    s.append(n.left)

        return list(preorder(root))
Example #29
0
    def path_sum_ii(self, root: typing.List[int],
                    sum: int) -> typing.List[typing.List[int]]:
        root = TreeNode.deserialize(root)
        res = []

        def dfs(root, slate, cur):
            if root is None: return
            if root.left is None and root.right is None:
                if cur + root.val == sum:
                    res.append(slate[:] + [root.val])
                    return
            slate.append(root.val)
            dfs(root.left, slate, cur + root.val)
            dfs(root.right, slate, cur + root.val)
            slate.pop()

        dfs(root, [], 0)
        return res
Example #30
0
    def upside_down(self, root: List[int]) -> TreeNode:
        root = TreeNode.deserialize(root)

        if not root: return None
        cur, s = root, [root]
        while cur.left is not None:
            cur = cur.left
            s.append(cur)

        new_root = cur = s.pop()
        while s:
            n = s.pop()
            cur.left = n.right
            cur.right = n
            n.left = n.right = None
            cur = n

        return new_root