Skip to content

Commit b73c0f2

Browse files
authored
Create README.md
1 parent 53887f7 commit b73c0f2

File tree

1 file changed

+221
-0
lines changed
  • 17 - Binary Tree Data Structure Problems/28 - Kth Ancestor in a 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'>Kth - Ansector - In a - Tree</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Kth Ancestor In a Tree](https://www.geeksforgeeks.org/problems/kth-ancestor-in-a-tree/1)
6+
7+
![image](https://github.com/user-attachments/assets/bab26c0d-9294-459c-b0e3-2ddad82208ca)
8+
![image](https://github.com/user-attachments/assets/87191a9a-897f-4855-a771-f042c5cdbcf3)
9+
![image](https://github.com/user-attachments/assets/b4518b3a-ef0d-456f-801a-2f7c10aa5888)
10+
11+
## Problem Explanation
12+
**Objective**:
13+
Given a binary tree, a node, and an integer `k`, find the kth ancestor of the given node. If the ancestor does not exist, return -1.
14+
15+
**Explanation**:
16+
- The kth ancestor of a node is the node that is `k` levels above it in the binary tree.
17+
- If `k = 1`, the output is the immediate parent.
18+
- If `k = 2`, the output is the parent of the parent, and so on.
19+
20+
**Example**:
21+
Consider the following tree:
22+
```
23+
1
24+
/ \
25+
2 3
26+
/ \
27+
4 5
28+
```
29+
1. If `node = 5` and `k = 1`, the output is `2` (parent of 5).
30+
2. If `node = 5` and `k = 2`, the output is `1` (grandparent of 5).
31+
3. If `node = 4` and `k = 3`, the output is `-1` since the 3rd ancestor does not exist.
32+
33+
### Step 2: Approach
34+
35+
**Goal**:
36+
We need to traverse the binary tree recursively to find the given node and then backtrack up `k` times to reach its ancestor.
37+
38+
**Steps**:
39+
1. Traverse the tree using recursion.
40+
2. When the target node is found, start counting upwards (i.e., decrease `k` at each ancestor level).
41+
3. Once `k` reaches zero, the current ancestor is the kth ancestor.
42+
4. If `k` becomes greater than the total levels above the node (no ancestor at `k` level), return `-1`.
43+
44+
**Key Insights**:
45+
- Use recursion to traverse and backtrack up the tree.
46+
- Maintain a count of steps (`k`) remaining to reach the desired ancestor.
47+
48+
## Problem Solution
49+
```cpp
50+
Node* solve(Node* root, int& k, int node){
51+
if(root == NULL) return NULL;
52+
53+
if(root -> data == node) return root;
54+
55+
Node* leftAns = solve(root -> left, k, node);
56+
Node* rightAns = solve(root -> right, k, node);
57+
58+
if(leftAns != NULL && rightAns == NULL){
59+
k--;
60+
if(k <= 0) {
61+
k = INT_MAX;
62+
return root;
63+
}
64+
65+
return leftAns;
66+
}
67+
68+
if(leftAns == NULL && rightAns != NULL){
69+
k--;
70+
if(k <= 0) {
71+
k = INT_MAX;
72+
return root;
73+
}
74+
75+
return rightAns;
76+
}
77+
78+
return NULL;
79+
}
80+
81+
int kthAncestor(Node *root, int k, int node)
82+
{
83+
Node* ancestor = solve(root, k, node);
84+
if(ancestor == NULL || ancestor -> data == node) return -1;
85+
86+
return ancestor->data;
87+
}
88+
89+
```
90+
91+
## Problem Solution Explanation
92+
Let's break down the provided source code for the "Kth Ancestor in a Tree" problem line by line, providing detailed explanations and examples where appropriate.
93+
94+
#### Function `solve(Node* root, int& k, int node)`
95+
96+
1. **`Node* solve(Node* root, int& k, int node)`**:
97+
- This function is a recursive helper function that aims to find the kth ancestor of a given node in a binary tree.
98+
- **Parameters**:
99+
- `Node* root`: Pointer to the current node being processed.
100+
- `int& k`: Reference to the integer `k`, which keeps track of how many levels we need to go up to find the ancestor.
101+
- `int node`: The value of the target node whose kth ancestor we want to find.
102+
103+
2. **`if (root == NULL) return NULL;`**:
104+
- This checks if the current node is NULL (i.e., we've reached the end of a branch in the tree).
105+
- If so, it returns NULL, indicating that we haven’t found the target node in this path.
106+
107+
3. **`if (root->data == node) return root;`**:
108+
- This checks if the current node's data matches the target node's data.
109+
- If it matches, it means we've found the target node, so we return the current node.
110+
111+
4. **`Node* leftAns = solve(root->left, k, node);`**:
112+
- This recursively calls the `solve()` function for the left child of the current node.
113+
- It stores the result (which could either be the target node or NULL) in the variable `leftAns`.
114+
115+
5. **`Node* rightAns = solve(root->right, k, node);`**:
116+
- Similar to the previous line, this recursively calls the `solve()` function for the right child of the current node and stores the result in `rightAns`.
117+
118+
#### Handling the Results from Left and Right Subtrees
119+
120+
6. **`if (leftAns != NULL && rightAns == NULL) {`**:
121+
- This checks if the target node was found in the left subtree (i.e., `leftAns` is not NULL) and not found in the right subtree (i.e., `rightAns` is NULL).
122+
- If this condition is true, it indicates that we need to move up one level in the tree.
123+
124+
7. **`k--;`**:
125+
- This decrements `k` because we are moving up one level in the tree, and we need to count how many levels we need to go up to find the kth ancestor.
126+
127+
8. **`if (k <= 0) {`**:
128+
- This checks if `k` has reached zero or below, which indicates that we have found the kth ancestor.
129+
- If this condition is true, we will reset `k` to avoid further ancestor checks and return the current node.
130+
131+
9. **`k = INT_MAX;`**:
132+
- This line sets `k` to a very high value (`INT_MAX`) so that subsequent calls do not mistakenly consider this node as a valid ancestor.
133+
- It's a flag indicating we found the kth ancestor.
134+
135+
10. **`return root;`**:
136+
- This returns the current node as it is the kth ancestor we are looking for.
137+
138+
11. **`return leftAns;`**:
139+
- If `k` is still greater than zero, it returns the result from the left subtree.
140+
141+
12. **`if (leftAns == NULL && rightAns != NULL) {`**:
142+
- This checks the opposite condition: whether the target node was found in the right subtree only.
143+
144+
13. **`k--;`**:
145+
- Similar to before, decrement `k` since we are moving up from the right child.
146+
147+
14. **`if (k <= 0) {`**:
148+
- This checks if `k` has reached zero, indicating we have found the kth ancestor from the right side.
149+
150+
15. **`k = INT_MAX;`**:
151+
- Again, we reset `k` to prevent further ancestor checks.
152+
153+
16. **`return root;`**:
154+
- Returns the current node as it is the kth ancestor.
155+
156+
17. **`return NULL;`**:
157+
- This line is reached when neither the left nor the right subtree contains the target node. It returns NULL to indicate that the node was not found.
158+
159+
### Function `kthAncestor(Node *root, int k, int node)`
160+
161+
18. **`int kthAncestor(Node *root, int k, int node) {`**:
162+
- This is the main function that users call to find the kth ancestor.
163+
- It initializes the search process.
164+
165+
19. **`Node* ancestor = solve(root, k, node);`**:
166+
- Calls the `solve()` function to find the ancestor. The result is stored in the `ancestor` variable.
167+
168+
20. **`if (ancestor == NULL || ancestor->data == node) return -1;`**:
169+
- This checks if no ancestor was found (i.e., `ancestor` is NULL) or if the found ancestor is actually the target node itself.
170+
- In either case, it returns `-1`, indicating that there is no valid kth ancestor.
171+
172+
21. **`return ancestor->data;`**:
173+
- Finally, if a valid ancestor is found, it returns the data of that ancestor.
174+
175+
### Example Walkthrough
176+
177+
Let's consider the tree structure for a clearer understanding:
178+
```
179+
1
180+
/ \
181+
2 3
182+
/ \
183+
4 5
184+
```
185+
186+
Assuming we want to find the 2nd ancestor of node `5`:
187+
- We call `kthAncestor(root, 2, 5)`.
188+
- The `solve` function starts at the root:
189+
- `root = 1`: Not equal to `5`, check left subtree.
190+
- `root = 2`: Not equal to `5`, check left subtree.
191+
- `root = 4`: Not equal to `5`, check left subtree (NULL).
192+
- Backtrack to `2`, now check right subtree:
193+
- `root = 5`: Found, return `5`.
194+
- Backtrack to `2`:
195+
- `k` is decremented to `1` (moving up one level).
196+
- Backtrack to `1`:
197+
- `k` is decremented to `0` (moving up another level).
198+
- Return `1`, which is the 2nd ancestor of `5`.
199+
200+
201+
Given the tree:
202+
```
203+
1
204+
/ \
205+
2 3
206+
/ \
207+
4 5
208+
```
209+
1. `kthAncestor(root, 1, 5)`:
210+
- **Output**: `2` (Immediate parent).
211+
2. `kthAncestor(root, 2, 5)`:
212+
- **Output**: `1` (Parent of parent).
213+
3. `kthAncestor(root, 3, 5)`:
214+
- **Output**: `-1` (No ancestor exists at 3 levels).
215+
216+
### Step 5: Time and Space Complexity
217+
218+
- **Time Complexity**: \(O(n)\), where \(n\) is the number of nodes. This is because in the worst case, we may need to traverse all nodes.
219+
- **Space Complexity**: \(O(h)\), where \(h\) is the height of the tree. This is the space required for the recursive call stack in a binary tree of height \(h\).
220+
221+
This solution efficiently handles binary trees of varying structures while finding the kth ancestor for any given node within the tree.

0 commit comments

Comments
 (0)