def removeLeafNodes(self, root: TreeNode, target: int) -> TreeNode: # This is essentially pruning, where nodes are deleted on a condition, but also the resulting # parents are removed if they also meet this condition # pruning amounts to POSTORDER traversal # RR: Prune left and right; if root matches condition remove the root if not root: return None root.left = self.removeLeafNodes(root.left, target) root.right = self.removeLeafNodes(root.right, target) return None if root.val == target and not root.left and not root.right else root
def flatten_tree(root: TreeNode): """ Flattens tree using reverse post-order traversal. :param root: root of tree :Time: O(N) :return: none """ global previous # Tracks the previously seen node to avoid a linear pass through the left list! if root: flatten_tree(root.right) flatten_tree(root.left) root.right = previous # Set right subtree to previously seen node root.left = None previous = root # Update previous
def prune_tree(root: TreeNode) -> TreeNode: """ Returns a pruned tree. Essentially removing all leaf nodes with value 0. :param root: root of tree :Time: O(N) :Space: O(N) :return: root of resulting tree """ if not root: # BC: If empty tree nothing to prune return None root.left, root.right = prune_tree(root.left), prune_tree( root.right) # prune left and right if root.key == 0 and (not root.left and not root.right): return None # If root is a leaf node with value 0, remove it else: return root
def flatten_suboptimal(root: TreeNode): """ Flattens tree in-place. Idea: Recursively flatten left subtree and right subtree. Get tail of left subtree (now a linked list). Repoint root.right to root.left and point the left tail's right to root.right :param root: root of tree :return: none """ if root: flatten_suboptimal(root.left) flatten_suboptimal(root.right) left_tail = root.left while left_tail and left_tail.right: left_tail = left_tail.right if left_tail: left_tail.right = root.right root.right, root.left = root.left, None
previous = None def flatten_tree(root: TreeNode): """ Flattens tree using reverse post-order traversal. :param root: root of tree :Time: O(N) :return: none """ global previous # Tracks the previously seen node to avoid a linear pass through the left list! if root: flatten_tree(root.right) flatten_tree(root.left) root.right = previous # Set right subtree to previously seen node root.left = None previous = root # Update previous if __name__ == '__main__': test = TreeNode(1) test.left = TreeNode(2) test.right = TreeNode(5) test.left.left = TreeNode(3) test.left.right = TreeNode(4) test.right.right = TreeNode(6) pretty_print_tree(test) flatten_tree(test) pretty_print_tree(test)
:Time: O(N) :Space: O(N) :return: list of largest values at each level """ if not root: return [] ret_val, bfs_queue = {}, [(root, 1)] while bfs_queue: removed, removed_level = bfs_queue.pop(0) if removed_level in ret_val: # update maximum if already seen this level ret_val[removed_level] = max(removed.key, ret_val[removed_level]) else: ret_val[removed_level] = removed.key # if not seen this level, assign current max # Add children if removed.left: bfs_queue.append((removed.left, removed_level + 1)) if removed.right: bfs_queue.append((removed.right, removed_level + 1)) return list(ret_val.values()) if __name__ == '__main__': t, a = TreeNode(1), [1, 3, 9] t.left = TreeNode(3) t.right = TreeNode(2) t.left.left = TreeNode(5) t.left.right = TreeNode(3) t.right.right = TreeNode(9) assert largest_values(t) == a, 'ERROR' print('PASSED')
def prune_tree(root: TreeNode) -> TreeNode: """ Returns a pruned tree. Essentially removing all leaf nodes with value 0. :param root: root of tree :Time: O(N) :Space: O(N) :return: root of resulting tree """ if not root: # BC: If empty tree nothing to prune return None root.left, root.right = prune_tree(root.left), prune_tree( root.right) # prune left and right if root.key == 0 and (not root.left and not root.right): return None # If root is a leaf node with value 0, remove it else: return root if __name__ == '__main__': t = TreeNode(1) t.left = TreeNode(0) t.right = TreeNode(1) t.left.left = TreeNode(0) t.left.right = TreeNode(0) t.right.left = TreeNode(0) t.right.right = TreeNode(1) pretty_print_tree(t) pretty_print_tree(prune_tree(t))
# BC2: if root is not an operator, i.e. just a value, then nothing to evaluate if not is_operator(root.key): return root.key else: # RC: root is an operator; get result of evaluation of the left and right subtree and operate on them return calculate(evaluate(root.left), root.key, evaluate(root.right)) if __name__ == '__main__': t1 = BinaryTree() t1.insert('/') t1.insert('*') t1.insert(4) t1.insert(2) t1.insert('+') t1.root.left.right.left = TreeNode(3) t1.root.left.right.right = TreeNode('/') t1.root.left.right.right.left = TreeNode(6) t1.root.left.right.right.right = TreeNode(2) print(evaluate(t1.root)) t2 = BinaryTree() t2.insert('/') t2.insert(8) t2.insert(4) print(evaluate(t2.root)) t3 = BinaryTree() t3.insert('+') t3.insert('*') t3.insert('-')
bfs_queue.append((removed.left, removed_level + 1)) if removed.left.key == x: x_par, x_lev = removed, removed_level + 1 if removed.left.key == y: y_par, y_lev = removed, removed_level + 1 if removed.right: bfs_queue.append((removed.right, removed_level + 1)) if removed.right.key == x: x_par, x_lev = removed, removed_level + 1 if removed.right.key == y: y_par, y_lev = removed, removed_level + 1 return x_lev == y_lev and x_par != y_par # true if same level and different parent if __name__ == '__main__': t1, t2, t3, a1, a2, a3 = TreeNode(1), TreeNode(1), TreeNode( 1), False, True, False t1.left = TreeNode(2) t1.right = TreeNode(3) t1.left.left = TreeNode(4) assert are_cousins(t1, 4, 3) == a1, 'ERROR!' t2.left = TreeNode(2) t2.right = TreeNode(3) t2.left.left = TreeNode(4) t2.right.right = TreeNode(5) assert are_cousins(t2, 5, 4) == a2, 'ERROR!' t3.left = TreeNode(2) t3.right = TreeNode(3) t3.left.left = TreeNode(4) assert are_cousins(t3, 2, 3) == a3, 'ERROR!' print('PASSED!')