|
| 1 | +<h1 align='center'>Kth - Largest - Element - In - BST</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Kth Largest Element in BST](https://www.geeksforgeeks.org/problems/kth-largest-element-in-bst/1) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +## Problem Explanation |
| 11 | +**Problem**: Given a Binary Search Tree (BST) and an integer `k`, we want to find the `k`th largest element in the BST. |
| 12 | + |
| 13 | +**Constraints**: |
| 14 | +- We need to find the element by traversing the BST in such a way that we efficiently locate the `k`th largest element. |
| 15 | +- BST property: In a BST, for each node, all values in the left subtree are smaller, and all values in the right subtree are larger. |
| 16 | + |
| 17 | +**Example**: |
| 18 | +For a BST like this: |
| 19 | + |
| 20 | +``` |
| 21 | + 5 |
| 22 | + / \ |
| 23 | + 3 8 |
| 24 | + / \ \ |
| 25 | + 2 4 10 |
| 26 | +``` |
| 27 | + |
| 28 | +If `k = 2`, the `2`nd largest element is `8`. |
| 29 | +If `k = 3`, the `3`rd largest element is `5`. |
| 30 | + |
| 31 | +**Real-world Analogy**: |
| 32 | +Imagine a leaderboard in a game where players are ranked by scores. Finding the `k`th largest score is like finding the `k`th highest scorer in a BST. |
| 33 | + |
| 34 | +**Edge Cases**: |
| 35 | +1. **Small BST**: A tree with only one node, where `k = 1`. |
| 36 | +2. **`k` Larger Than Node Count**: If `k` is greater than the number of nodes in the BST, the function should return an error or a sentinel value (like `-1`) to indicate this. |
| 37 | +3. **`k = 0` or Negative `k`**: This is an invalid input, and the function should handle it appropriately. |
| 38 | + |
| 39 | +--- |
| 40 | + |
| 41 | +### Step 2: Approach |
| 42 | + |
| 43 | +#### High-Level Overview |
| 44 | +The task requires finding the `k`th largest element, which suggests an in-order traversal but in reverse order (right-root-left) since we want descending values. |
| 45 | + |
| 46 | +#### Step-by-Step Breakdown |
| 47 | +1. **Reverse In-order Traversal**: In a BST, a reverse in-order traversal (right-root-left) will give us nodes in descending order. |
| 48 | +2. **Count Nodes**: While traversing in reverse order, keep a count of nodes visited so far. |
| 49 | +3. **Find `k`th Node**: Stop the traversal as soon as the count matches `k`; this is our answer. |
| 50 | + |
| 51 | +**Example Walkthrough**: |
| 52 | +Using the same tree: |
| 53 | +``` |
| 54 | + 5 |
| 55 | + / \ |
| 56 | + 3 8 |
| 57 | + / \ \ |
| 58 | + 2 4 10 |
| 59 | +``` |
| 60 | + |
| 61 | +Let's find the `2`nd largest element: |
| 62 | +1. Start at the root (5) and go to the right subtree (8). |
| 63 | +2. Go further right to 10 (largest element). `Count = 1`. |
| 64 | +3. Return to 8. Now, `Count = 2` (matches `k`). So, `8` is the answer. |
| 65 | + |
| 66 | +#### Pseudocode |
| 67 | +```pseudo |
| 68 | +function kthLargest(root, k): |
| 69 | + initialize count = 0 |
| 70 | + perform reverseInOrderTraversal(root) |
| 71 | + |
| 72 | + function reverseInOrderTraversal(node): |
| 73 | + if node is null: |
| 74 | + return |
| 75 | + reverseInOrderTraversal(node.right) |
| 76 | + count++ |
| 77 | + if count == k: |
| 78 | + result = node.data |
| 79 | + return |
| 80 | + reverseInOrderTraversal(node.left) |
| 81 | +``` |
| 82 | + |
| 83 | +## Problem Solution |
| 84 | +```cpp |
| 85 | +class Solution { |
| 86 | + public: |
| 87 | + int solve(Node* root, int &i, int k){ |
| 88 | + if(root == NULL) return -1; |
| 89 | + |
| 90 | + int right = solve(root -> right, i, k); |
| 91 | + if(right != -1) return right; |
| 92 | + |
| 93 | + i++; |
| 94 | + if(i == k) return root -> data; |
| 95 | + |
| 96 | + return solve(root -> left, i, k); |
| 97 | + } |
| 98 | + |
| 99 | + int kthLargest(Node *root, int k) { |
| 100 | + int i = 0; |
| 101 | + int ans = solve(root, i, k); |
| 102 | + |
| 103 | + return ans; |
| 104 | + } |
| 105 | +}; |
| 106 | +``` |
| 107 | +
|
| 108 | +## Problem Solution Explanation |
| 109 | +
|
| 110 | +Here's the given C++ code with a detailed line-by-line explanation. |
| 111 | +
|
| 112 | +```cpp |
| 113 | +class Solution { |
| 114 | + public: |
| 115 | + int solve(Node* root, int &i, int k){ |
| 116 | +``` |
| 117 | + |
| 118 | +- **Line 1-3**: We define a class `Solution` with a method `solve`. This helper function uses recursion to perform the reverse in-order traversal (right-root-left). |
| 119 | +- **Parameters**: |
| 120 | + - `root`: The root node of the current subtree. |
| 121 | + - `i`: A reference to a counter that tracks how many nodes we’ve visited. |
| 122 | + - `k`: The `k`th position we’re trying to find. |
| 123 | + |
| 124 | + |
| 125 | +```cpp |
| 126 | + if(root == NULL) return -1; |
| 127 | +``` |
| 128 | + |
| 129 | +- **Line 5**: If `root` is `NULL`, it means we’ve reached the end of a branch, so we return `-1` as a sentinel value indicating that we haven’t found the `k`th largest element yet. |
| 130 | + |
| 131 | + |
| 132 | +```cpp |
| 133 | + int right = solve(root->right, i, k); |
| 134 | +``` |
| 135 | + |
| 136 | +- **Line 6**: We perform a recursive call on the right subtree. This traversal starts from the largest values (rightmost nodes) in the BST. |
| 137 | +- **Store Result**: We store the result of the recursive call in `right` to check if the `k`th largest element has been found. |
| 138 | + |
| 139 | + |
| 140 | +```cpp |
| 141 | + if(right != -1) return right; |
| 142 | +``` |
| 143 | + |
| 144 | +- **Line 7**: If `right` is not `-1`, it means we have already found the `k`th largest element in the right subtree. We return `right` up the recursive call stack to finish the function early. |
| 145 | + |
| 146 | + |
| 147 | +```cpp |
| 148 | + i++; |
| 149 | + if(i == k) return root->data; |
| 150 | +``` |
| 151 | + |
| 152 | +- **Line 9-10**: If we haven’t found the `k`th largest element yet, we increment the counter `i`. |
| 153 | + - If `i` equals `k`, then `root->data` is the `k`th largest element in the BST, so we return `root->data`. |
| 154 | + |
| 155 | + |
| 156 | +```cpp |
| 157 | + return solve(root->left, i, k); |
| 158 | + } |
| 159 | +``` |
| 160 | + |
| 161 | +- **Line 12**: If `i` is still not equal to `k`, we continue the traversal by exploring the left subtree. |
| 162 | +- **Purpose**: This ensures that we move to smaller values only after checking the larger values. |
| 163 | + |
| 164 | +```cpp |
| 165 | + int kthLargest(Node *root, int k) { |
| 166 | + int i = 0; |
| 167 | + int ans = solve(root, i, k); |
| 168 | + |
| 169 | + return ans; |
| 170 | + } |
| 171 | +}; |
| 172 | +``` |
| 173 | +
|
| 174 | +- **Line 15-20**: The `kthLargest` function initializes the counter `i` to `0` and calls `solve` with `root`, `i`, and `k`. |
| 175 | +- The result from `solve` is stored in `ans`, which we then return as the final answer. |
| 176 | +
|
| 177 | +### Step 4: Output Examples |
| 178 | +
|
| 179 | +**Example 1**: For the given tree: |
| 180 | +``` |
| 181 | + 5 |
| 182 | + / \ |
| 183 | + 3 8 |
| 184 | + / \ \ |
| 185 | + 2 4 10 |
| 186 | +``` |
| 187 | +- **Input**: `k = 2` |
| 188 | +- **Output**: `8` |
| 189 | +
|
| 190 | +**Example 2**: For `k = 4`: |
| 191 | +- **Input**: `k = 4` |
| 192 | +- **Output**: `5` |
| 193 | +
|
| 194 | +**Explanation**: |
| 195 | +- We start from the largest values in descending order. When `k = 4`, the nodes visited are `10 -> 8 -> 5`, so the 4th largest is `5`. |
| 196 | +
|
| 197 | +
|
| 198 | +### Step 5: Time and Space Complexity |
| 199 | +
|
| 200 | +**Time Complexity**: `O(H + k)` |
| 201 | +- **Explanation**: We only visit nodes until we find the `k`th largest element. In the worst case, we visit `H + k` nodes, where `H` is the height of the tree, since we traverse down the right side first. |
| 202 | +- In a balanced BST, `H = log N`, making the time complexity close to `O(log N + k)`. |
| 203 | +
|
| 204 | +**Space Complexity**: `O(H)` |
| 205 | +- **Explanation**: The space complexity is `O(H)` because of the recursion stack during traversal. This is the maximum depth of recursive calls we’ll have, which is proportional to the height of the BST. |
| 206 | +
|
| 207 | +
|
| 208 | +This approach is efficient because it leverages the BST properties and only traverses the necessary nodes to find the `k`th largest element without requiring extra space for storing elements. |
0 commit comments