235. Lowest Common Ancestor of a Binary Search Tree
Iterative solution
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
// Make p the lowest node
if (p.val > q.val) {
const temp = p;
p = q;
q = temp;
}
let curr = root;
while(curr) {
if (p.val < curr.val && q.val < curr.val) {
curr = curr.left;
} else if (p.val > curr.val && q.val > curr.val) {
curr = curr.right;
} else {
return curr;
}
}
};
Recursive Solution
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
if (!root) {
return null;
}
// Make p the lowest node
if (p.val > q.val) {
const temp = p;
p = q;
q = temp;
}
if (root.val === p.val || root.val === q.val) {
// Root is one of the searched nodes
return root;
} else if (p.val < root.val && q.val > root.val) {
// Split. Root is the common ancestor.
return root;
} else if (p.val < root.val && q.val < root.val) {
// Left sub-tree
return lowestCommonAncestor(root.left, p, q);
} else {
// Right sub-tree
return lowestCommonAncestor(root.right, p, q);
}
};
Complexity
- Time Complexity: O(logN), because we visit only one node for every level of the tree.
- Space Complexity: O(1), there is no extra memory used. For the resursive approach is O(logN) because of the implicit call stack.