|
| 1 | +""" |
| 2 | +Problem: |
| 3 | +----------------------------------------------- |
| 4 | +https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/ |
| 5 | +
|
| 6 | +Given a binary search tree that contains unique values and two nodes within the tree, a, and b, |
| 7 | +return their lowest common ancestor. |
| 8 | +Note: the lowest common ancestor of two nodes is |
| 9 | +the deepest node within the tree such that both nodes are descendants of it. |
| 10 | +Ex: Given the following tree... |
| 11 | + 7 |
| 12 | + / \ |
| 13 | + 2 9 |
| 14 | + / \ |
| 15 | + 1 5 |
| 16 | +and a = 1, b = 9, return a reference to the node containing 7. |
| 17 | +Ex: Given the following tree... |
| 18 | + 8 |
| 19 | + / \ |
| 20 | + 3 9 |
| 21 | + / \ |
| 22 | + 2 6 |
| 23 | +and a = 2, b = 6, return a reference to the node containing 3. |
| 24 | +Ex: Given the following tree... |
| 25 | + 8 |
| 26 | + / \ |
| 27 | + 6 9 |
| 28 | +and a = 6, b = 8, return a reference to the node containing 8. |
| 29 | +
|
| 30 | +
|
| 31 | +Naive Solution: |
| 32 | +----------------------------------------------- |
| 33 | +@description: |
| 34 | +A simple solution would be to store the path from root to x |
| 35 | +and the path from the root to y in two auxiliary arrays. |
| 36 | +Then traverse both arrays simultaneously till the values in the arrays match. |
| 37 | +The last matched value will be the LCA. |
| 38 | +If the end of one array is reached, then the last seen value is LCA. |
| 39 | +Either p or q is the root => return root |
| 40 | +
|
| 41 | +@complexity: |
| 42 | +Time: O(n), for a binary search tree with n nodes |
| 43 | +Space: O(n), for storing two arrays |
| 44 | +
|
| 45 | +
|
| 46 | +Solution: |
| 47 | +----------------------------------------------- |
| 48 | +@description: |
| 49 | +We can recursively find the lowest common ancestor of nodes x and y present in the BST. |
| 50 | +The trick is to find the BST node, |
| 51 | +which has one key present in its left subtree and the other key present in the right subtree. |
| 52 | +If any such node is present in the tree, then it is LCA |
| 53 | +If y lies in the subtree rooted at node x, then x is the LCA |
| 54 | +Otherwise, if x lies in the subtree rooted at node y, then y is the LCA |
| 55 | +
|
| 56 | +@complexity: |
| 57 | +Recursive: |
| 58 | +Time: O(n), for a binary search tree with n nodes |
| 59 | +Space: O(h), it requires space proportional to the tree’s height for the call stack |
| 60 | +Iterative: |
| 61 | +Time: O(n), for a binary search tree with n nodes |
| 62 | +Space: O(1), no auxiliary space required |
| 63 | +""" |
| 64 | + |
| 65 | + |
| 66 | +class Node: |
| 67 | + def __init__(self, key=0, left=None, right=None): |
| 68 | + self.key = key |
| 69 | + self.left = left |
| 70 | + self.right = right |
| 71 | + |
| 72 | + |
| 73 | +class Solution: |
| 74 | + def LCArecursive(self, root, p, q): |
| 75 | + # Base case: empty tree |
| 76 | + if root is None: |
| 77 | + return None |
| 78 | + |
| 79 | + # If both p and q are smaller than the root, LCA exists in the left subtree |
| 80 | + if root.key > max(p.key, q.key): |
| 81 | + return self.LCArecursive(root.left, p, q) |
| 82 | + |
| 83 | + # If both p and q are greater than the root, LCA exists in the right subtree |
| 84 | + elif root.key < min(p.key, q.key): |
| 85 | + return self.LCArecursive(root.right, p, q) |
| 86 | + |
| 87 | + # If one key is greater (or equal) to the root |
| 88 | + # and one key is smaller (or equal) than the root |
| 89 | + # then the current node is LCA |
| 90 | + return root |
| 91 | + |
| 92 | + def LCAiterative(self, root, p, q): |
| 93 | + if root is None: |
| 94 | + return None |
| 95 | + |
| 96 | + curr = root |
| 97 | + |
| 98 | + while curr: |
| 99 | + if curr.key > max(p.key, q.key): |
| 100 | + curr = curr.left |
| 101 | + elif curr.key < min(p.key, q.key): |
| 102 | + curr = curr.right |
| 103 | + else: |
| 104 | + return curr |
| 105 | + |
| 106 | + return curr |
0 commit comments