|
| 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 | + |
| 8 | + |
| 9 | + |
| 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