Binary Trees 2 -------------- Lowest Common Ancestor --------------------- > LCA(n1, n2) is the node which is accessible from both n1, n2 (while going up), and is farthest from the root > Given a Tree and 2 nodes, find LCA > k-ary tree **Approach 1:** - traverse from each node to root - bottom up - compare the two paths from left to right - O(n^2) time, O(n) space **Approach 2:** - traverse from each node to root - bottom up - compare from root to node - top down - O(n) time, O(n) space **Approach 3:** - don't store all parents. Use linked list intersection technique - count the height of each path. - traverse the longer path so height is same - move up together - stop when same node - O(1) space > Can't go from child to parent? > Don't have pointers to nodee we have values which must be searched > Distinct values ```python def lca(key1, key2, node): if node.value in [key1, key2]: return node left = lca(key1, key2, node.left) right = lca(key1, key2, node.right) if left is not None and right is not None: return node if left is not None: return left if right is not None: return right return None lca(key1, key2, root) ``` -- -- Isomorphism ----------- > Rotate tree to reach another row ```python def isomorphic(node1, node2): if node1 != node2: return False # binary if isomorphic(node1.left, node2.left) and isomorphic(node1.right, node2.right): return True if isomorphic(node1.left, node2.right) and isomorphic(node1.right, node2.left): return True return False # O(n). Each node visited at most twice # k-ary for children1 in permute(node1.children): for children2 in permute(node2.children): passed = True for c1, c2 in zip(children1, children2): if not isomorphic(c1, c2): passed = False break if passed: return True return False # sort tree in level order recursively first, then compare ``` -- -- Longest Increasing Consequtive Sequence -------------------------------------------------- > has to be top-down > has to be connected > has to be continuous (1-2-3 is okay, 1-3-5 is not) > - recursive - func returns length of the LICS at node - find LICS of left and right - if left = node + 1, then LICS+1 - max of left, right -- -- Create Next Pointers with O(1) space ------------------------------------ - Simple using O(n) space. Just do level order traversal - can't use recursion either, because have to maintain call stack, which is O(h) - todo ```python level_start = root while level_start: cur = level_start while cur is not None: if cur.left: if cur.right: cur.left.next = cur.right else: cur.left.next = get_next_child(cur) if cur.right: cur.right.next = get_next_child(cur) cur = cur.next if level_start.left: level_start = level_start.left elif level_start.right: level_start = level_start.right else: level_start = None def get_next_child(node): iterate to get the child, till children exist if not, then move to node.next guaranteed to have precomputed the next ``` -- -- Boundary of tree ---------------- Tree of same sum ---------------- -- -- > Why cant decide tree using pre+post order? why need inorder? inorder: lst root rst preorder: root lst rst postorder: lst rst root if just have preorder+postorder, can't separate lst-rst