class Solution: def isCompleteTree(self, root: TreeNode) -> bool: queue = deque([root]) while True: currNode = queue.popleft() if not currNode.left: if currNode.right: return False else: # Found the first leaf node. break queue.append(currNode.left) if not currNode.right: # Found the parent of the first leaf node. break queue.append(currNode.right) # From this moment, we have two cases: # 1. When it jumps from the first leaf node, all the following node # in the remaining queue should not have any child node. # 2. When it jumps from the parent of the first leaf node, then it # also means all the following node the remaining queue should # not have any child node. return not any(node.left or node.right for node in queue) root = TreeNode(1) root.create_tree({1: (2, 3), 2: (None, None), 3: (7, 8)}) print(Solution().isCompleteTree(root))
class Solution: def addOneRow(self, root: TreeNode, v: int, d: int) -> TreeNode: """ Traverse the original tree level by level. """ if d == 1: newRoot = TreeNode(v) newRoot.left = root return newRoot currNodes = [root] for _ in range(2, d): # Get all the nodes on the d - 1 level. currNodes = [ x for currNode in currNodes for x in (currNode.left, currNode.right) if x ] for currNode in currNodes: left, right = currNode.left, currNode.right currNode.left = TreeNode(v) currNode.right = TreeNode(v) currNode.left.left = left currNode.right.right = right return root root = TreeNode(4) root.create_tree({4: (2, 6), 2: (3, 1), 6: (5, None)}) print(Solution().addOneRow(root, 1, 2).print_tree())
""" https://leetcode.com/problems/maximum-difference-between-node-and-ancestor/ """ from test_helper import TreeNode class Solution: def maxAncestorDiff(self, root: TreeNode) -> int: def check(curr: TreeNode, currMax: int, currMin: int) -> int: if not curr: return currMax - currMin nextMax = max(currMax, curr.val) nextMin = min(currMin, curr.val) return max(check(curr.left, nextMax, nextMin), check(curr.right, nextMax, nextMin)) return check(root, root.val, root.val) root = TreeNode(8) root.create_tree({ 8: (3, 10), 3: (1, 6), 6: (4, 7), 10: (None, 14), 14: (None, 13) }) print(Solution().maxAncestorDiff(root))
class Solution: def sumNumbers(self, root: TreeNode) -> int: """ Use level by level traverse. """ if not root: # Empty tree. return 0 totalSum, queue = 0, deque([(root, root.val)]) while queue: node, currSum = queue.popleft() if not node.left and not node.right: totalSum += currSum continue if node.left: queue.append((node.left, currSum * 10 + node.left.val)) if node.right: queue.append((node.right, currSum * 10 + node.right.val)) return totalSum givenDict = { 1: (2, 3) } root = TreeNode(1) root.create_tree(givenDict) print(Solution().sumNumbers(root))
# Calculate the last level. maxWidth = max(maxWidth, currEnd - currStart + 1) return maxWidth def widthOfBinaryTree2(self, root: TreeNode) -> int: """ Same idea with much shorter form. """ if not root: return 0 nodesOnEachLevel = [(1, root)] # (index, node) maxWidth = 1 while nodesOnEachLevel: maxWidth = max( maxWidth, nodesOnEachLevel[-1][0] - nodesOnEachLevel[0][0] + 1) nodesOnEachLevel = [ nextItem for preIdx, preNode in nodesOnEachLevel for nextItem in enumerate((preNode.left, preNode.right), start=preIdx << 1) if nextItem[1] ] return maxWidth root = TreeNode(1) root.create_tree({1: (2, 3), 2: (4, 5), 3: (None, 7)}) print(Solution().widthOfBinaryTree(root))
from test_helper import TreeNode from typing import List class Solution: def printTree(self, root: TreeNode) -> List[List[str]]: def calc_height(root: TreeNode) -> int: if not root: return 0 return 1 + max(calc_height(root.left), calc_height(root.right)) def fill(currNode: TreeNode, r: int, start: int, end: int) -> None: if currNode: m = start + ((end - start) >> 1) rslt[r][m] = str(currNode.val) fill(currNode.left, r + 1, start, m - 1) fill(currNode.right, r + 1, m + 1, end) R = calc_height(root) C = (1 << R) - 1 rslt = [[''] * C for _ in range(R)] fill(root, 0, 0, C - 1) return rslt root = TreeNode(1) root.create_tree({1: (2, 3), 2: (None, 4)}) print(Solution().printTree(root))
""" https://leetcode.com/problems/convert-bst-to-greater-tree/ """ from test_helper import TreeNode class Solution: def convertBST(self, root: TreeNode) -> TreeNode: currNode, stack, pre = root, [], 0 while currNode or stack: while currNode: stack.append(currNode) currNode = currNode.right currNode = stack.pop() currNode.val += pre pre = currNode.val currNode = currNode.left return root root = TreeNode(5) root.create_tree({5: (2, 13)}) print(Solution().convertBST(root))
""" https://leetcode.com/problems/insert-into-a-binary-search-tree/ """ from test_helper 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 root = TreeNode(4) root.create_tree({4: (2, 7), 2: (1, 3)}) print(Solution().insertIntoBST(root, 5).print_tree())
""" Taking advantage of BST and inorder traversal. """ n1, n2, s1, s2, rslt = root1, root2, [], [], [] while n1 or n2 or s1 or s2: while n1: s1.append(n1) n1 = n1.left while n2: s2.append(n2) n2 = n2.left if not s2 or (s1 and s1[-1].val <= s2[-1].val): n1 = s1.pop() rslt.append(n1.val) n1 = n1.right else: n2 = s2.pop() rslt.append(n2.val) n2 = n2.right return rslt root1 = TreeNode(0) root1.create_tree({0: (None, 59), 59: (57, 90)}) root2 = TreeNode(60) root2.create_tree({60: (17, 74), 17: (6, 20), 74: (63, 97), 97: (95, None)}) print(list(Solution()._in_order(root1)))
For a perfect binary tree, if its height is h, the total nodes it has is 2^0 + 2^1 + ... + 2^(h - 1) = 2^0 * (1 - 2^h) / (1 - 2) = 2^h - 1. """ nodeCnt, currNode, rootHeight = 0, root, self.get_height(root) while currNode: leftHeight = rootHeight - 1 rightHeight = self.get_height(currNode.right) if leftHeight == rightHeight: # The left sub tree is a perfect binary tree. # So the total nodes in root and its left sub tree is: # 1 + 2 ^ h - 1 = 2 ^ h. nodeCnt += 1 << leftHeight currNode = currNode.right else: # The right sub tree is a perfect binary tree. # So the total nodes in root and its right sub tree is: # 1 + 2 ^ h - 1 = 2 ^ h. nodeCnt += 1 << rightHeight currNode = currNode.left rootHeight -= 1 return nodeCnt root = TreeNode(1) root.create_tree({1: (2, 3), 2: (4, 5), 3: (6, None)}) print(Solution().countNodes(root))
""" Use stack to rebuild the tree. """ if not data: return None stack, vals = [], data.split() root = currNode = TreeNode(int(vals[0])) for i in range(1, len(vals)): val = int(vals[i]) if val < currNode.val: currNode.left = TreeNode(val) stack.append(currNode) currNode = currNode.left else: while stack and stack[-1].val < val: currNode = stack.pop() currNode.right = TreeNode(val) currNode = currNode.right return root root = TreeNode(5) root.create_tree({5: (3, 6), 3: (2, 4), 2: (1, None)}) c = Codec() s = c.serialize(root) print(s) print(c.deserialize(s).print_tree())
1. The maximum money when the current node is not robbed. 2. The maximum money when the current node is robbed. """ if not currNode: # Cannot rob anything. return [0] * 2 left = rob_each(currNode.left) right = rob_each(currNode.right) # Calculate the max money when the current node is not robbed. # We could either rob its left or right node or not rob them. # Just get the maximum money from both cases. m1 = max(left) + max(right) # Calculate the max money when the current node is robbed. # In this case we should not rob either its left or right node. m2 = currNode.val + left[0] + right[0] return [m1, m2] return max(rob_each(root)) root = TreeNode(1) root.create_tree(givenDict={ 1: (2, 3), 2: (4, 5), 3: (6, 7) }) print(Solution().rob(root))
class Solution: def deleteNode(self, root: TreeNode, key: int) -> TreeNode: if not root: return None if root.val < key: root.right = self.deleteNode(root.right, key) elif root.val > key: root.left = self.deleteNode(root.left, key) else: # Root is the target node to be deleted. if not root.left: return root.right elif not root.right: return root.left else: # Update the root value with the minimum value on its right # sub tree, then delete the old minimum tree node. curr = root.right while curr.left: curr = curr.left root.val = curr.val root.right = self.deleteNode(root.right, root.val) return root root = TreeNode(5) root.create_tree({5: (3, 6), 3: (2, 4), 6: (None, 7)}) print(Solution().deleteNode(root, 3).print_tree())