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
return 0, None left_depth, left = deepest(root.left) right_depth, right = deepest(root.right) if left_depth == right_depth: return left_depth + 1, root elif left_depth > right_depth: return left_depth + 1, left else: return right_depth + 1, right return deepest(root)[1] # TESTS for tree, expected in [ ("1,#,#", "1,#,#"), ("1,2,#,#,#", "2,#,#"), ("0,1,#,2,#,#,3,#,#", "2,#,#"), ("3,5,6,#,#,2,7,#,#,4,#,#,1,0,#,#,8,#,#", "2,7,#,#,4,#,#"), ( "1,2,4,#,#,5,8,10,#,#,11,#,#,9,12,#,#,13,#,#,3,6,#,#,#", "5,8,10,#,#,11,#,#,9,12,#,#,13,#,#", ), ]: sol = Solution() actual = TreeNode.serialize( sol.lcaDeepestLeaves(TreeNode.deserialize(tree))) print("The lowest common ancestor of its deepest leaves in", tree, "->", actual) assert actual == expected
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 searchBST(self, root: TreeNode, val: int) -> TreeNode: if not root: return None if root.val == val: return root elif val < root.val: return self.searchBST(root.left, val) else: return self.searchBST(root.right, val) # TESTS tests = [ ["#", 0, None], ["1,#,#", 1, 1], ["4,2,1,#,#,3,#,#,7,#,#", 2, 2], ["4,2,1,#,#,3,#,#,7,#,#", 1, 1], ["4,2,1,#,#,3,#,#,7,#,#", 7, 7], ["4,2,1,#,#,3,#,#,7,#,#", 5, None], ] for t in tests: sol = Solution() actual = sol.searchBST(TreeNode.deserialize(t[0]), t[1]) print("Search", t[1], "in", t[0], "->", TreeNode.serialize(actual)) if t[2] is None: assert actual is None else: assert actual.val == t[2]
class Solution: 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 # TESTS for tree, expected in [ ["#", "#"], ["1", "1,#,#"], ["1,2,#,#,#", "1,#,2,#,#"], ["1,#,2,#,#", "1,2,#,#,#"], ["1,2,#,#,3,#,#", "1,3,#,#,2,#,#"], ["1,2,3,#,#,#,#", "1,#,2,#,3,#,#"], ["1,#,2,#,3,#,#", "1,2,3,#,#,#,#"], ["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,4,#,#,3,#,#,#"], ]: sol = Solution() actual = TreeNode.serialize(sol.invertTree(TreeNode.deserialize(tree))) print("Invert tree", tree, "->", actual) assert actual == expected
from local_packages.binary_tree import TreeNode class Solution: 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 # TESTS tests = [ ("#", 1, "1,#,#"), ("4,2,1,#,#,3,#,#,7,#,#", 5, "4,2,1,#,#,3,#,#,7,5,#,#,#"), ( "40,20,10,#,#,30,#,#,60,50,#,#,70,#,#", 25, "40,20,10,#,#,30,25,#,#,#,60,50,#,#,70,#,#", ), ] for tree, val, expected in tests: sol = Solution() actual_tree = sol.insertIntoBST(TreeNode.deserialize(tree), val) actual = TreeNode.serialize(actual_tree) print("Insert", val, "into", tree, "->", actual) assert actual == expected
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 # TESTS for tree, key, expected in [ ["#", 1, "#"], ["1,#,#", 2, "1,#,#"], ["1,#,#", 1, "#"], ["1,#,2,#,#", 1, "2,#,#"], ["2,1,#,#,3,#,#", 2, "3,1,#,#,#"], ["2,1,#,#,3,#,#", 3, "2,1,#,#,#"], ["5,3,2,#,#,4,#,#,6,#,7,#,#", 3, "5,4,2,#,#,#,6,#,7,#,#"], ]: sol = Solution() actual = TreeNode.serialize( sol.deleteNode(TreeNode.deserialize(tree), key) ) print("Delete", key, "from", tree, "->", actual) assert actual == expected
from local_packages.binary_tree import TreeNode class Solution: 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 # TESTS for tree, low, high, expected in [ ("1,0,#,#,2,#,#", 1, 2, "1,#,2,#,#"), ("3,0,#,2,1,#,#,#,4,#,#", 1, 3, "3,2,1,#,#,#,#"), ("1,#,#", 1, 2, "1,#,#"), ("1,#,2,#,#", 1, 3, "1,#,2,#,#"), ("1,#,2,#,#", 2, 4, "2,#,#"), ]: sol = Solution() actual = TreeNode.serialize(sol.trimBST(TreeNode.deserialize(tree), low, high)) print("Trim BST", tree, "->", actual) assert actual == expected
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right from typing import List, Optional from functools import lru_cache from local_packages.binary_tree import TreeNode class Solution: def generateTrees(self, n: int) -> List[Optional[TreeNode]]: @lru_cache 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] return trees(1, n) # TESTS for n in range(1, 5): sol = Solution() actual = sol.generateTrees(n) print("Unique BST of n =", n, "->", [TreeNode.serialize(t) for t in actual])
# self.val = val # self.left = left # self.right = right from typing import List from local_packages.binary_tree import TreeNode class Solution: 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 :]), ) # TESTS for preorder, inorder, expected in [ ([1], [1], "1,#,#"), ([1, 2], [2, 1], "1,2,#,#,#"), ([1, 2], [1, 2], "1,#,2,#,#"), ([3, 9, 20, 15, 7], [9, 3, 15, 20, 7], "3,9,#,#,20,15,#,#,7,#,#"), ]: sol = Solution() actual = TreeNode.serialize(sol.buildTree(preorder, inorder)) print("Build Tree ->", actual) assert actual == expected
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), ) # TESTS for array, expected in [ ([-10, -3, 0, 5, 9], "0,-3,-10,#,#,#,9,5,#,#,#"), ([], "#"), ([0], "0,#,#"), ([1, 3], "3,1,#,#,#"), ([1, 2, 3, 4], "3,2,1,#,#,#,4,#,#"), ]: sol = Solution() actual = TreeNode.serialize(sol.sortedListToBST( ListNode.from_array(array))) print("Convert sorted list", array, "to BST ->", actual) assert actual == expected
# self.right = right from local_packages.binary_tree import TreeNode class Solution: def convertBST(self, root: TreeNode) -> TreeNode: def fold(p: TreeNode, s: int) -> int: if not p: return s p.val += fold(p.right, s) return fold(p.left, p.val) fold(root, 0) return root # TESTS for tree, expected in [ ( "4,1,0,#,#,2,#,3,#,#,6,5,#,#,7,#,8,#,#", "30,36,36,#,#,35,#,33,#,#,21,26,#,#,15,#,8,#,#", ), ("0,#,1,#,#", "1,#,1,#,#"), ("1,0,#,#,2,#,#", "3,3,#,#,2,#,#"), ("3,2,1,#,#,#,4,#,#", "7,9,10,#,#,#,4,#,#"), ]: sol = Solution() actual = TreeNode.serialize(sol.convertBST(TreeNode.deserialize(tree))) print("Convert BST", tree, "to greater tree ->", actual) assert actual == expected
if not root: return 0, None left_depth, left = deepest(root.left) right_depth, right = deepest(root.right) if left_depth == right_depth: return left_depth + 1, root elif left_depth > right_depth: return left_depth + 1, left else: return right_depth + 1, right return deepest(root)[1] # TESTS for tree, expected in [ ("1,#,#", "1,#,#"), ("1,2,#,#,#", "2,#,#"), ("0,1,#,2,#,#,3,#,#", "2,#,#"), ("3,5,6,#,#,2,7,#,#,4,#,#,1,0,#,#,8,#,#", "2,7,#,#,4,#,#"), ( "1,2,4,#,#,5,8,10,#,#,11,#,#,9,12,#,#,13,#,#,3,6,#,#,#", "5,8,10,#,#,11,#,#,9,12,#,#,13,#,#", ), ]: sol = Solution() actual = TreeNode.serialize( sol.subtreeWithAllDeepest(TreeNode.deserialize(tree))) print("Smallest Subtree with all the Deepest Nodes in", tree, "->", actual) assert actual == expected
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 return left_not_contain_1 and right_not_contain_1 and root.val == 0 return None if not_contain_1(root) else 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 # TESTS for tree, expected in [ ("1,#,0,0,#,#,1,#,#", "1,#,0,#,1,#,#"), ("1,0,0,#,#,0,#,#,1,0,#,#,1,#,#", "1,#,1,#,1,#,#"), ("1,1,1,0,#,#,#,1,#,#,0,0,#,#,1,#,#", "1,1,1,#,#,1,#,#,0,#,1,#,#"), ]: sol = Solution() actual = TreeNode.serialize(sol.pruneTree(TreeNode.deserialize(tree))) print("Prune subtree non containing 1 from", 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
class Solution: 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 # TESTS tests = [ ([], [], "#"), ([1], [1], "1,#,#"), ([2, 1], [2, 1], "1,2,#,#,#"), ([1, 2], [2, 1], "1,#,2,#,#"), ([2, 1, 3], [2, 3, 1], "1,2,#,#,3,#,#"), ([9, 3, 15, 20, 7], [9, 15, 7, 20, 3], "3,9,#,#,20,15,#,#,7,#,#"), ] for t in tests: sol = Solution() actual = TreeNode.serialize(sol.buildTree(t[0], t[1])) print("Construct from", t[0], t[1], "->", actual) assert actual == t[2]
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
# self.right = None from typing import List, Optional from local_packages.binary_tree import TreeNode class Solution: def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]: 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 return build(preorder[::-1], float("Inf")) for preorder, expected in [ [[], "#"], [[1], "1,#,#"], [[2, 1], "2,1,#,#,#"], [[2, 3], "2,#,3,#,#"], [[2, 1, 3], "2,1,#,#,3,#,#"], [[8, 5, 1, 7, 10, 12], "8,5,1,#,#,7,#,#,10,#,12,#,#"], ]: sol = Solution() actual = TreeNode.serialize(sol.bstFromPreorder(preorder)) print("BST from preorder traversal", preorder, "->", actual) assert actual == expected