Beispiel #1
0
 def increasingBST(self, root: TreeNode, nxt: TreeNode = None) -> TreeNode:
     if not root:
         return nxt
     head = self.increasingBST(root.left, root)
     root.left = None
     root.right = self.increasingBST(root.right, nxt)
     return head
Beispiel #2
0
 def build(xs: List[int], ubound: int) -> Optional[TreeNode]:
     if not xs or xs[-1] > ubound:
         return None
     root = TreeNode(xs.pop())
     root.left = build(xs, root.val)
     root.right = build(xs, ubound)
     return root
Beispiel #3
0
 def pruneTreeV2(self, root: TreeNode) -> TreeNode:
     if not root:
         return None
     root.left = self.pruneTree(root.left)
     root.right = self.pruneTree(root.right)
     if not root.left and not root.right and not root.val:
         return None
     return root
Beispiel #4
0
 def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
     if not root:
         return TreeNode(val)
     if val < root.val:
         root.left = self.insertIntoBST(root.left, val)
     else:
         root.right = self.insertIntoBST(root.right, val)
     return root
 def treeToDoublyList(self, root: TreeNode) -> TreeNode:
     if not root:
         return None
     lhead = self.treeToDoublyList(root.left)
     rhead = self.treeToDoublyList(root.right)
     # make root itself a single node DLL
     root.left = root
     root.right = root
     return self.connect(self.connect(lhead, root), rhead)
Beispiel #6
0
 def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode:
     if not root:
         return root
     if root.val < low:
         return self.trimBST(root.right, low, high)
     elif root.val > high:
         return self.trimBST(root.left, low, high)
     else:
         root.left = self.trimBST(root.left, low, root.val)
         root.right = self.trimBST(root.right, root.val, high)
         return root
Beispiel #7
0
 def _deserialize(buffer: List[str], lower: int,
                  upper: int) -> "TreeNode":
     if len(buffer) == 0:
         return None
     if buffer[0] < lower or buffer[0] > upper:
         return None
     val = buffer.pop(0)
     root = TreeNode(val)
     root.left = _deserialize(buffer, lower, val)
     root.right = _deserialize(buffer, val, upper)
     return root
Beispiel #8
0
 def addOneRow(self,
               root: TreeNode,
               v: int,
               d: int,
               left: bool = True) -> TreeNode:
     if d == 1:
         nroot = TreeNode(v, root if left else None, None if left else root)
         return nroot
     if not root:
         return root
     root.left = self.addOneRow(root.left, v, d - 1, True)
     root.right = self.addOneRow(root.right, v, d - 1, False)
     return root
Beispiel #9
0
 def invertTree(self, root: TreeNode) -> TreeNode:
     if not root:
         return root
     left = self.invertTree(root.left)
     right = self.invertTree(root.right)
     root.left, root.right = right, left
     return root
Beispiel #10
0
 def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
     if root is None:
         return root
     if key < root.val:
         root.left = self.deleteNode(root.left, key)
     elif key > root.val:
         root.right = self.deleteNode(root.right, key)
     else:  # found the key
         if root.left is None:
             return root.right
         if root.right is None:
             return root.left
         min_val = self.findMin(root.right)
         root.val = min_val
         root.right = self.deleteNode(root.right, min_val)
     return root
Beispiel #11
0
 def trees(first: int, last: int) -> List[Optional[TreeNode]]:
     return [
         TreeNode(root, left, right)
         for root in range(first, last + 1)
         for left in trees(first, root - 1)
         for right in trees(root + 1, last)
     ] or [None]
Beispiel #12
0
 def helper(p: TreeNode):
     nonlocal pre
     if not p:
         return p
     helper(p.right)
     helper(p.left)
     p.left, p.right = None, pre
     pre = p
Beispiel #13
0
 def pruneTreeV1(self, root: TreeNode) -> TreeNode:
     def not_contain_1(root: TreeNode) -> bool:
         if not root:
             return True
         if left_not_contain_1 := not_contain_1(root.left):
             root.left = None
         if right_not_contain_1 := not_contain_1(root.right):
             root.right = None
Beispiel #14
0
    def sortedListToBST(self, head: ListNode) -> TreeNode:
        if not head:
            return None
        if not head.next:
            return TreeNode(head.val)

        pslow, slow, fast = None, head, head
        while fast and fast.next:
            pslow, slow = slow, slow.next
            fast = fast.next.next
        pslow.next = None

        return TreeNode(
            slow.val,
            left=self.sortedListToBST(head),
            right=self.sortedListToBST(slow.next),
        )
Beispiel #15
0
 def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
     if not preorder:
         return None
     i = inorder.index(preorder[0])
     return TreeNode(
         val=preorder[0],
         left=self.buildTree(preorder[1 : i + 1], inorder[:i]),
         right=self.buildTree(preorder[i + 1 :], inorder[i + 1 :]),
     )
 def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
     if not nums:
         return None
     mid = len(nums) // 2
     return TreeNode(
         nums[mid],
         self.sortedArrayToBST(nums[:mid]),
         self.sortedArrayToBST(nums[mid + 1:]),
     )
 def connect(self, h1: TreeNode, h2: TreeNode) -> TreeNode:
     if not h1:
         return h2
     if not h2:
         return h1
     t1, t2 = h1.left, h2.left
     h2.left, t1.right = t1, h2
     t2.right, h1.left = h1, t2
     return h1
Beispiel #18
0
 def helper(p: TreeNode) -> TreeNode:
     if not p or (not p.left and not p.right):
         return p
     right = p.right
     ltail = helper(p.left)
     if ltail:
         p.left, p.right = None, p.left
         ltail.right = right
     return helper(right) if right else ltail
Beispiel #19
0
 def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
     assert len(inorder) == len(postorder)
     if len(inorder) == 0:
         return None
     root_index = inorder.index(postorder[-1])
     root = TreeNode(
         postorder[-1],
         self.buildTree(inorder[:root_index], postorder[:root_index]),
         self.buildTree(inorder[root_index + 1 :], postorder[root_index:-1]),
     )
     return root
Beispiel #20
0
 def helper(node: TreeNode) -> Tuple[TreeNode, TreeNode]:
     if not node:
         return None, None
     if node.left:
         head, ltail = helper(node.left)
         ltail.right, node.left = node, None
     else:
         head = node
     if node.right:
         node.right, rtail = helper(node.right)
     else:
         rtail = node
     return head, rtail
Beispiel #21
0
    def recoverTree(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        first, second, prev = None, None, TreeNode(float("-Inf"))

        def helper(node: TreeNode) -> None:
            nonlocal first, second, prev
            if not node:
                return

            helper(node.left)
            # in-order validation for the incorrect
            if not first and prev.val > node.val:
                first = prev
            if first and prev.val > node.val:
                second = node
            prev = node

            helper(node.right)

        helper(root)
        first.val, second.val = second.val, first.val
Beispiel #22
0
                rtail = node
            return head, rtail

        head, _ = helper(root)
        return head

    def increasingBST(self, root: TreeNode, nxt: TreeNode = None) -> TreeNode:
        if not root:
            return nxt
        head = self.increasingBST(root.left, root)
        root.left = None
        root.right = self.increasingBST(root.right, nxt)
        return head


# TESTS
for tree, expected in [
    ("1,#,#", "1,#,#"),
    ("1,#,2,#,#", "1,#,2,#,#"),
    ("2,1,#,#,#", "1,#,2,#,#"),
    ("5,1,#,#,7,#,#", "1,#,5,#,7,#,#"),
    ("3,2,1,#,#,#,4,#,#,", "1,#,2,#,3,#,4,#,#"),
    ("6,#,8,7,#,#,9,#,#", "6,#,7,#,8,#,9,#,#"),
    ("5,3,2,1,#,#,#,4,#,#,6,#,8,7,#,#,9,#,#", "1,#,2,#,3,#,4,#,5,#,6,#,7,#,8,#,9,#,#"),
]:
    sol = Solution()
    actual = TreeNode.serialize(sol.increasingBSTV1(TreeNode.deserialize(tree)))
    print("Increasing BST of", tree, "->", actual)
    assert actual == expected
    assert expected == TreeNode.serialize(sol.increasingBST(TreeNode.deserialize(tree)))
Beispiel #23
0

class Solution:
    def addOneRow(self,
                  root: TreeNode,
                  v: int,
                  d: int,
                  left: bool = True) -> TreeNode:
        if d == 1:
            nroot = TreeNode(v, root if left else None, None if left else root)
            return nroot
        if not root:
            return root
        root.left = self.addOneRow(root.left, v, d - 1, True)
        root.right = self.addOneRow(root.right, v, d - 1, False)
        return root


# TESTS
for tree, v, d, expected in [
    ("4,#,#", 1, 1, "1,4,#,#,#"),
    ("4,2,3,#,#,1,#,#,6,5,#,#,#", 1, 2, "4,1,2,3,#,#,1,#,#,#,1,#,6,5,#,#,#"),
    ("4,2,3,#,#,1,#,#,#", 1, 3, "4,2,1,3,#,#,#,1,#,1,#,#,#"),
    ("1,2,4,#,#,#,3,#,#", 5, 4, "1,2,4,5,#,#,5,#,#,#,3,#,#"),
]:
    sol = Solution()
    actual = TreeNode.serialize(sol.addOneRow(TreeNode.deserialize(tree), v,
                                              d))
    print("Add a row", v, "to depth", d, "to tree", tree, "->", actual)
    assert actual == expected
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
from local_packages.binary_tree import TreeNode
from typing import List


class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        if not nums:
            return None
        mid = len(nums) // 2
        return TreeNode(
            nums[mid],
            self.sortedArrayToBST(nums[:mid]),
            self.sortedArrayToBST(nums[mid + 1:]),
        )


# TESTS
for nums, expected in [
    ([-10, -3, 0, 5, 9], "0,-3,-10,#,#,#,9,5,#,#,#"),
    ([1, 3], "3,1,#,#,#"),
    ([], "#"),
]:
    sol = Solution()
    actual = TreeNode.serialize(sol.sortedArrayToBST(nums))
    print("Convert", nums, "to BST ->", actual)
    assert actual == expected
Beispiel #25
0
        def dfs(node: TreeNode, pathsum: int, path: List[int]) -> None:
            if not node:
                return
            pathsum += node.val
            path.append(node.val)
            if pathsum == targetSum and node.left is None and node.right is None:
                ans.append(list(path))
            dfs(node.left, pathsum, path)
            dfs(node.right, pathsum, path)
            path.pop()

        dfs(root, 0, [])
        return ans


# TESTS
for tree, targetSum, expected in [
    ("5,4,11,7,#,#,2,#,#,#,8,13,#,#,4,5,#,#,1,#,#", 22, [[5, 4, 11, 2],
                                                         [5, 8, 4, 5]]),
    ("1,2,#,#,3,#,#", 5, []),
    ("1,2,#,#,#", 0, []),
    ("1,2,#,#,3,#,#", 4, [[1, 3]]),
    ("1,2,#,#,#", 3, [[1, 2]]),
    ("#", 0, []),
]:
    sol = Solution()
    actual = sol.pathSum(TreeNode.deserialize(tree), targetSum)
    print(tree, "all paths with sum equals", targetSum, "->", actual)
    assert actual == expected
Beispiel #26
0
#         self.right = right
from local_packages.binary_tree import TreeNode


class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def helper(root: TreeNode) -> (bool, int):
            if not root:
                return True, 0
            lres, lht = helper(root.left)
            rres, rht = helper(root.right)
            return lres and rres and abs(lht - rht) <= 1, max(lht, rht) + 1

        return helper(root)[0]


# TESTS
for tree, expected in [
    ("#", True),
    ("1,#,#", True),
    ("1,2,#,#,#", True),
    ("1,#,2,#,3,#,#", False),
    ("1,2,#,#,3,#,#", True),
    ("3,9,#,#,20,15,#,#,7,#,#", True),
    ("1,2,3,4,#,#,4,#,#,3,#,#,2,#,#", False),
]:
    sol = Solution()
    actual = sol.isBalanced(TreeNode.deserialize(tree))
    print("Is", tree, "balanced? ->", actual)
    assert actual == expected
#         self.right = right
from typing import Optional, Tuple
from local_packages.binary_tree import TreeNode


class Solution:
    def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
        def helper(root: Optional[TreeNode]) -> Tuple[int, int]:
            if not root:
                return 0, 0
            ldep, ldia = helper(root.left)
            rdep, rdia = helper(root.right)
            return max(ldep, rdep) + 1, max(ldia, rdia, ldep + rdep)

        return helper(root)[1]


# TESTS
for tree, expected in [
    ["#", 0],
    ["1,#,#", 0],
    ["1,2,#,#,#", 1],
    ["1,2,#,#,3,#,#", 2],
    ["1,2,4,#,#,5,#,#,3,#,#", 3],
    ["1,2,4,6,7,#,#,#,#,5,#,8,#,9,#,#,3,#,#", 6],
]:
    sol = Solution()
    actual = sol.diameterOfBinaryTree(TreeNode.deserialize(tree))
    print("Diameter of", tree, "->", actual)
    assert actual == expected
Beispiel #28
0
        def helper(p: TreeNode):
            nonlocal pre
            if not p:
                return p
            helper(p.right)
            helper(p.left)
            p.left, p.right = None, pre
            pre = p

        helper(root)


# TESTS
for tree, expected in [
    ("#", "#"),
    ("0,#,#", "0,#,#"),
    ("1,2,#,#,#", "1,#,2,#,#"),
    ("1,#,2,#,#", "1,#,2,#,#"),
    ("1,2,#,#,3,#,#", "1,#,2,#,3,#,#"),
    ("1,2,3,#,#,#,#", "1,#,2,#,3,#,#"),
    ("1,#,2,#,3,#,#", "1,#,2,#,3,#,#"),
    ("1,2,3,#,#,4,#,#,5,#,6,#,#", "1,#,2,#,3,#,4,#,5,#,6,#,#"),
]:
    sol = Solution()
    root = TreeNode.deserialize(tree)
    sol.flattenV2(root)
    actual = TreeNode.serialize(root)
    print("Flatten", tree, "->", actual)
    assert actual == expected
        while queue:
            ans.append([node.val for node in queue[::dir]])
            dir *= -1
            next_level = []
            for node in queue:
                if node.left:
                    next_level.append(node.left)
                if node.right:
                    next_level.append(node.right)
            queue = next_level
        return ans


# TESTS
tests = [
    ("#", []),
    ("1,#,#", [[1]]),
    ("1,2,#,#,3,#,#", [[1], [3, 2]]),
    ("1,2,3,4,#,#,#,#,#", [[1], [2], [3], [4]]),
    ("1,#,2,#,3,#,4,#,#", [[1], [2], [3], [4]]),
    ("1,#,2,3,4,#,#,#,#", [[1], [2], [3], [4]]),
    ("1,#,2,3,#,#,4,#,#", [[1], [2], [3, 4]]),
    ("3,9,#,#,20,15,#,#,7,#,#", [[3], [20, 9], [15, 7]]),
    ("3,9,#,11,#,#,20,15,#,#,7,#,#", [[3], [20, 9], [11, 15, 7]]),
]
for t in tests:
    sol = Solution()
    actual = sol.zigzagLevelOrder(TreeNode.deserialize(t[0]))
    print("Zigzag level order of", t[0], "->", actual)
    assert actual == t[1]
Beispiel #30
0
#         self.right = right

from local_packages.binary_tree import TreeNode


class Solution:
    def maxAncestorDiff(self, root: TreeNode) -> int:
        def helper(node: TreeNode, lower: int, upper: int) -> int:
            if not node:
                return upper - lower
            lower, upper = min(lower, node.val), max(upper, node.val)
            return max(
                helper(node.left, lower, upper), helper(node.right, lower, upper)
            )

        assert root != None
        return helper(root, root.val, root.val)


# TESTS
for tree, expected in [
    ("1,2,#,#,4,#,#", 3),
    ("1,#,2,#,3,#,#", 2),
    ("8,3,1,#,#,6,4,#,#,7,#,#,10,#,14,13,#,#,#", 7),
    ("1,#,2,#,0,3,#,#,#", 3),
]:
    sol = Solution()
    actual = sol.maxAncestorDiff(TreeNode.deserialize(tree))
    print("Maximum Difference Between Node and Ancestor", tree, "->", actual)
    assert actual == expected