Skip to content

Commit 76514f0

Browse files
authored
Create README.md
1 parent 57d7cdd commit 76514f0

File tree

1 file changed

+221
-0
lines changed
  • 17 - Binary Tree Data Structure Problems/25 - LCA in Binary Tree

1 file changed

+221
-0
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<h1 align='center'>LCA - in Binary - Tree</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [LCA in Binary Tree](https://www.geeksforgeeks.org/problems/lowest-common-ancestor-in-a-binary-tree/1?itm_source=geeksforgeeks&itm_medium=article&itm_campaign=practice_card)
6+
7+
![image](https://github.com/user-attachments/assets/04f9127c-0588-4bdf-9d63-05e1be65c1d2)
8+
![image](https://github.com/user-attachments/assets/b19c9a1f-a9d8-44c1-b17c-7ac13c16a1a6)
9+
![image](https://github.com/user-attachments/assets/dbcf1e04-34fd-47f1-81eb-47afaf34a341)
10+
11+
## Problem Explanation
12+
13+
**Clarity and Conciseness:**
14+
The problem is to find the Lowest Common Ancestor (LCA) of two nodes in a binary tree. The LCA of two nodes \( n1 \) and \( n2 \) in a binary tree is defined as the deepest node that is an ancestor of both nodes. The function should return a pointer to the LCA node.
15+
16+
**Input:**
17+
- A binary tree (represented by its root node).
18+
- Two integers, \( n1 \) and \( n2 \), which are the values of the nodes for which we need to find the LCA.
19+
20+
**Output:**
21+
- A pointer/reference to the node that is the LCA of the two given nodes.
22+
23+
**Constraints:**
24+
- The tree may be empty (root can be NULL).
25+
- The nodes may or may not be present in the tree.
26+
27+
**Real-world Analogy:**
28+
Consider a family tree where each person is represented as a node. The LCA of two family members (e.g., siblings) is the closest ancestor (e.g., their parent). This concept helps in determining relationships within a hierarchy.
29+
30+
**Edge Cases:**
31+
- Both nodes are the same (the LCA is the node itself).
32+
- One or both nodes do not exist in the tree (the function should return NULL).
33+
- The tree is empty (the function should return NULL).
34+
35+
### Step 2: Approach
36+
37+
**High-Level Overview:**
38+
To find the LCA, we can use a recursive approach that traverses the binary tree. The idea is to traverse the tree starting from the root and explore left and right subtrees. We check if the current node is one of the nodes we are looking for and then combine the results of the left and right subtree searches.
39+
40+
**Step-by-Step Breakdown:**
41+
1. **Base Case:** If the current node is NULL, return NULL.
42+
2. **Check Current Node:** If the current node matches either \( n1 \) or \( n2 \), return the current node.
43+
3. **Recursive Search:**
44+
- Recursively search for \( n1 \) and \( n2 \) in the left subtree.
45+
- Recursively search for \( n1 \) and \( n2 \) in the right subtree.
46+
4. **Determine the LCA:**
47+
- If both left and right subtree calls return non-NULL, the current node is the LCA.
48+
- If only one of the calls returns a non-NULL value, return that value.
49+
- If both calls return NULL, return NULL.
50+
51+
**Visual Aids:**
52+
```
53+
1
54+
/ \
55+
2 3
56+
/ \ / \
57+
4 5 6 7
58+
```
59+
For this tree, if \( n1 = 4 \) and \( n2 = 5 \), the LCA is \( 2 \).
60+
61+
**Pseudocode:**
62+
```plaintext
63+
function lca(root, n1, n2):
64+
if root is NULL:
65+
return NULL
66+
67+
if root.data == n1 or root.data == n2:
68+
return root
69+
70+
left = lca(root.left, n1, n2)
71+
right = lca(root.right, n1, n2)
72+
73+
if left is not NULL and right is not NULL:
74+
return root
75+
if left is not NULL:
76+
return left
77+
if right is not NULL:
78+
return right
79+
80+
return NULL
81+
```
82+
83+
## Problem Solution
84+
```cpp
85+
class Solution
86+
{
87+
public:
88+
//Function to return the lowest common ancestor in a Binary Tree.
89+
Node* lca(Node* root ,int n1 ,int n2 )
90+
{
91+
if(root == NULL) return NULL;
92+
93+
if(root -> data == n1 || root -> data == n2) return root;
94+
95+
Node* leftAns = lca(root -> left, n1, n2);
96+
Node* rightAns = lca(root -> right, n1, n2);
97+
98+
if(leftAns != NULL && rightAns != NULL) return root;
99+
else if(leftAns != NULL && rightAns == NULL) return leftAns;
100+
else if(leftAns == NULL && rightAns != NULL) return rightAns;
101+
else return NULL;
102+
}
103+
};
104+
```
105+
106+
## Problem Solution Explanation
107+
108+
Here’s the given code with a line-by-line explanation:
109+
110+
```cpp
111+
class Solution {
112+
public:
113+
// Function to return the lowest common ancestor in a Binary Tree.
114+
Node* lca(Node* root, int n1, int n2) {
115+
```
116+
- **Class Declaration:** A class named `Solution` containing the function `lca`.
117+
- **Function Declaration:** The function `lca` takes three parameters: the root of the tree and two integers \( n1 \) and \( n2 \).
118+
119+
```cpp
120+
if(root == NULL) return NULL;
121+
```
122+
- **Base Case:** If the current node (root) is NULL, return NULL, indicating that the node is not found in this path.
123+
124+
```cpp
125+
if(root->data == n1 || root->data == n2) return root;
126+
```
127+
- **Check Current Node:** If the current node’s data matches either \( n1 \) or \( n2 \), return the current node as a potential LCA.
128+
129+
```cpp
130+
Node* leftAns = lca(root->left, n1, n2);
131+
Node* rightAns = lca(root->right, n1, n2);
132+
```
133+
- **Recursive Calls:** Recursively call `lca` for the left and right children of the current node, storing the results in `leftAns` and `rightAns`.
134+
135+
```cpp
136+
if(leftAns != NULL && rightAns != NULL) return root;
137+
```
138+
- **Determine LCA:** If both `leftAns` and `rightAns` are non-NULL, it means that \( n1 \) is found in one subtree and \( n2 \) in the other, so the current node is the LCA.
139+
140+
```cpp
141+
else if(leftAns != NULL && rightAns == NULL) return leftAns;
142+
```
143+
- If \( n1 \) or \( n2 \) is found only in the left subtree, return `leftAns`.
144+
145+
```cpp
146+
else if(leftAns == NULL && rightAns != NULL) return rightAns;
147+
```
148+
- If \( n1 \) or \( n2 \) is found only in the right subtree, return `rightAns`.
149+
150+
```cpp
151+
else return NULL;
152+
}
153+
};
154+
```
155+
- If neither of the nodes is found, return NULL, indicating that both nodes are not present in this subtree.
156+
157+
### Step 4: Output Examples
158+
159+
Let’s consider some test cases with explanations:
160+
161+
**Example 1:**
162+
```
163+
Tree:
164+
1
165+
/ \
166+
2 3
167+
/ \
168+
4 5
169+
170+
Input: n1 = 4, n2 = 5
171+
Output: 2
172+
```
173+
- **Explanation:** Nodes 4 and 5 are children of node 2, making 2 the LCA.
174+
175+
**Example 2:**
176+
```
177+
Tree:
178+
1
179+
/ \
180+
2 3
181+
/ \
182+
4 5
183+
184+
Input: n1 = 4, n2 = 3
185+
Output: 1
186+
```
187+
- **Explanation:** Node 1 is the LCA because node 3 is in a different subtree than nodes 4.
188+
189+
**Example 3:**
190+
```
191+
Tree:
192+
1
193+
/ \
194+
2 3
195+
/ \
196+
4 5
197+
198+
Input: n1 = 6, n2 = 5
199+
Output: NULL
200+
```
201+
- **Explanation:** Node 6 is not present in the tree, so the output is NULL.
202+
203+
### Step 5: Time and Space Complexity
204+
205+
**Time Complexity:**
206+
- **O(N)**: In the worst case, we may have to visit every node in the tree to find \( n1 \) and \( n2 \). Therefore, the time complexity is linear in terms of the number of nodes \( N \).
207+
208+
**Space Complexity:**
209+
- **O(H)**: The space complexity is determined by the height of the tree. In the worst case (for example, in a skewed tree), the height \( H \) could be equal to \( N \), giving a space complexity of O(N). In a balanced binary tree, the height \( H \) would be \( O(\log N) \).
210+
211+
**Detailed Analysis:**
212+
- **Time Complexity Explanation:** Each recursive call processes one node. The total number of nodes in the tree is \( N \), leading to \( O(N) \) total time complexity.
213+
214+
- **Space Complexity Explanation:** The maximum depth of the recursive call stack will be equal to the height of the tree. Hence, in the case of a balanced tree, the space will be \( O(\log N) \) and in the case of a skewed tree, it will be \( O(N) \).
215+
216+
**Optimizations:**
217+
- There is no significant optimization available for this problem since the algorithm must examine every relevant node. However, ensuring the tree is balanced can help optimize the space complexity in practice.
218+
219+
### Summary
220+
221+
The "LCA in Binary Tree" problem is a classic algorithm problem that can be solved with a straightforward recursive approach. Understanding the recursive nature and visualizing the tree structure are key to grasping how the solution works. This detailed breakdown provides a comprehensive understanding of the problem, solution approach, code functionality, and the complexity analysis involved.

0 commit comments

Comments
 (0)