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
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
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
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)
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
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
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
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
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
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]
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
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
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), )
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
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
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
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
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
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)))
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
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
# 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
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]
# 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