def helper(in_left=0, in_right=len(inorder)): nonlocal pre_idx if in_left == in_right: return None root_val = preorder[pre_idx] root = Tree(root_val) index = idx_map[root_val] pre_idx += 1 root.left = helper(in_left, index) root.right = helper(index + 1, in_right) return root
def make_tree(happy_tree) -> Tree: if isinstance(happy_tree[0], int): return Tree(happy_tree[0]) branches = happy_tree[0][1] root = Tree(happy_tree[0][0]) prev = root for ix, branch in enumerate(happy_tree): lefts = branch[1] if lefts: prev.left = make_tree(lefts) if ix == 0: continue t = Tree(branch[0]) prev.right = t prev = t return root
def traverse_find( self, root: Optional[Tree], target: int, *, depth: int = 0, parent: Tree, ) -> Tuple[int, Tree]: if root is None: return -1, Tree(-1) if root.v == target: return depth, parent depth_1, parent_1 = self.traverse_find(root.left, target, depth=depth + 1, parent=root) depth_2, parent_2 = self.traverse_find(root.right, target, depth=depth + 1, parent=root) if depth_1 > depth_2: return depth_1, parent_1 else: return depth_2, parent_2
def insertIntoBST(self, root, val): if root == None: return Tree(val) if val < root.val: root.left = self.insertIntoBST(root.left, val) else: root.right = self.insertIntoBST(root.right, val) return root
def isCousins(self, root: Tree, x: int, y: int) -> bool: depth_x, parent_x = self.traverse_find( root, x, parent=Tree(-1)) # sentinel parent depth_y, parent_y = self.traverse_find( root, y, parent=Tree(-1)) # sentinel parent return parent_x != parent_y and depth_x == depth_y
if root.v == target: return depth, parent depth_1, parent_1 = self.traverse_find(root.left, target, depth=depth + 1, parent=root) depth_2, parent_2 = self.traverse_find(root.right, target, depth=depth + 1, parent=root) if depth_1 > depth_2: return depth_1, parent_1 else: return depth_2, parent_2 # get the depth of x, get the depth of y # if both are on the same depth AND parents different = cousins def isCousins(self, root: Tree, x: int, y: int) -> bool: depth_x, parent_x = self.traverse_find( root, x, parent=Tree(-1)) # sentinel parent depth_y, parent_y = self.traverse_find( root, y, parent=Tree(-1)) # sentinel parent return parent_x != parent_y and depth_x == depth_y if __name__ == "__main__": t = Tree(1, Tree(2, None, Tree(4)), Tree(3)) s = Solution() s.isCousins(t, 2, 3) ...
#!/usr/bin/env python from solutions.minions import Tree from typing import List # Breadth First Search # You move each level at a time # all the children of the current level nodes are printed left to right # --------------------- BREADTH FIRST SEARCHES ------------------------ bfs_tree = Tree(1, Tree(2, Tree(4), Tree(5)), Tree(3)) def breadth_first_search(tree: Tree, prev_children: List[Tree] = None) -> None: if prev_children is None: print(tree.v) immediate_children = [] if prev_children: for child in prev_children: if child is not None: print(child.v) immediate_children.append(child.left) immediate_children.append(child.right) else: immediate_children = [tree.left, tree.right] # ! this check is very inefficient if all(x is None for x in immediate_children): return return breadth_first_search(tree, immediate_children) # ----------------------- DEPTH FIRST SEARCHES -------------------------- # you traverse down as far as possible. However, the order in which you print # varies between the below three
#!/usr/bin/env python from typing import Optional from solutions.minions import Tree # ! S=O(N) number of nodes are stored in the recursion stack frames. average case though is O(H) height of the tree # T = O(N) def tree_diamter(t: Tree) -> int: ans = 0 def depth(t: Optional[Tree]) -> int: nonlocal ans if t is None: return 0 L = depth(t.left) R = depth(t.right) ans = max(ans, L + R) return max(L, R) + 1 return depth(t) if __name__ == '__main__': print(tree_diamter(Tree(1, Tree(2), Tree(3))))