Lowest Common Ancestor of a Binary Tree - Complete Solution Guide
Lowest Common Ancestor of a Binary Tree is LeetCode problem 236, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According to the definition of LCA on Wikipedia : “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself ).” Example 1: Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 Output: 3 Explanation: The LCA of nodes 5 and 1 is 3. Example 2: Input: root = [3,5,1,6,2,0,8,nu
Detailed Explanation
The problem asks us to find the Lowest Common Ancestor (LCA) of two given nodes, `p` and `q`, in a binary tree. The LCA is defined as the lowest node in the tree that has both `p` and `q` as descendants (including the possibility that a node can be a descendant of itself). The input consists of the root of a binary tree and the two nodes `p` and `q` that are guaranteed to exist in the tree and are distinct. The output should be the TreeNode representing the LCA of `p` and `q`. The number of nodes in the tree is between 2 and 10^5, node values are unique and within a specified range.
Solution Approach
The solution uses a recursive DFS traversal of the binary tree. The recursion effectively searches the left and right subtrees for the target nodes `p` and `q`. The function returns a node when either of the following conditions are met: the current node is null, the current node is one of the target nodes, or the current node is the LCA. The magic happens in the recursive calls and how their results are combined.
Step-by-Step Algorithm
- Step 1: Base Case: If the current node `root` is null or if `root` is equal to `p` or `q`, return `root` immediately. This is because either we've reached the end of a branch, or we've found one of the nodes we're looking for.
- Step 2: Recursive Calls: Recursively call the function on the left and right subtrees: `left = lowestCommonAncestor(root.left, p, q)` and `right = lowestCommonAncestor(root.right, p, q)`. These calls explore the subtrees.
- Step 3: Check for LCA: After the recursive calls return, check if both `left` and `right` are non-null. If both are non-null, it means that one of the target nodes (`p` or `q`) was found in the left subtree and the other was found in the right subtree. In this case, the current `root` is the LCA, so return `root`.
- Step 4: Return Results: If only one of `left` or `right` is non-null, it means that one of the subtrees contains either one of the target nodes or the LCA of the target nodes. Return the non-null value. If both `left` and `right` are null, it means neither `p` nor `q` were found in the current subtree, so return `null`.
Key Insights
- Insight 1: The core idea is to use a recursive Depth-First Search (DFS) to traverse the tree. If we find either `p` or `q`, we return it up the call stack. This is because either `p` or `q` could be the LCA.
- Insight 2: The recursive calls will propagate upward. If at any node, the left subtree returns `p` and the right subtree returns `q` (or vice-versa), then that node is the LCA because it is the lowest node that contains both `p` and `q` as descendants.
- Insight 3: If only one of the subtrees returns a node, then that node is either the LCA (if the other node is a descendant of it) or one of the target nodes (`p` or `q`) itself.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(n)
Topics
This problem involves: Tree, Depth-First Search, Binary Tree.
Companies
Asked at: Atlassian, BitGo, Flipkart, GE Healthcare, Intuit, LinkedIn, MongoDB, Myntra, Oracle, Salesforce, Snapdeal, Wix, Yandex.