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 """
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
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)]
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
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
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
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
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))
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))
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))
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)
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
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)
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
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)]
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
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
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)
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
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))
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
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