Skip to content

Commit 1cd84ca

Browse files
authored
Create README.md
1 parent bcaa8e7 commit 1cd84ca

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
<h1 align='center'>K-th - Smallest - Element - In BST</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [K-th Smallest Element in BST](https://www.geeksforgeeks.org/problems/find-k-th-smallest-element-in-bst/1)
6+
7+
![image](https://github.com/user-attachments/assets/77cc928d-585c-4040-b372-91091de8d497)
8+
![image](https://github.com/user-attachments/assets/5f2aafbb-052e-4cf9-b44a-78b785f60f15)
9+
10+
## Problem Explanation
11+
The task is to find the **Kth smallest element in a Binary Search Tree (BST)**. A BST has the property that for any node, the left subtree has nodes with values less than the node's value, and the right subtree has nodes with values greater than the node's value.
12+
13+
Given:
14+
- A BST with `n` nodes.
15+
- An integer `k`, where `1 ≤ k ≤ n`.
16+
17+
Goal:
18+
- Return the value of the Kth smallest element in the BST.
19+
20+
#### Example
21+
22+
If the BST is:
23+
24+
```
25+
5
26+
/ \
27+
3 7
28+
/ \ \
29+
2 4 8
30+
```
31+
32+
- **K = 3**: The 3rd smallest element is `4`.
33+
- **K = 1**: The 1st smallest element is `2`.
34+
35+
#### Edge Cases
36+
37+
1. **Empty Tree**: If the BST has no nodes, the function should return `-1` (or handle the case gracefully).
38+
2. **Invalid `k`**: If `k` is larger than the number of nodes in the BST, it’s an invalid input.
39+
3. **Single Node Tree**: If the BST has only one node, the Kth smallest element is the value of that node if `k=1`.
40+
41+
### Step 2: Approach
42+
43+
**Morris Traversal** (also known as Threaded Binary Tree traversal) is an efficient method that allows **in-order traversal without using recursion or a stack**. It uses **O(1) additional space**.
44+
45+
1. **In-Order Traversal**: The smallest elements are visited in increasing order using in-order traversal in a BST.
46+
2. **Count Nodes**: Count each node during the traversal, and when the count equals `k`, we've found our answer.
47+
48+
#### Steps of Morris Traversal
49+
50+
1. Start from the root node.
51+
2. For each node:
52+
- If it has no left child, visit this node and move to the right child.
53+
- If it has a left child, find its **in-order predecessor** (the rightmost node in the left subtree).
54+
- If the right pointer of the predecessor is null, make the current node its right child temporarily, then move to the left child.
55+
- If the right pointer of the predecessor points to the current node, break this temporary link, visit the current node, and move to the right child.
56+
3. Stop when we've found the Kth smallest element.
57+
58+
## Problem Solution
59+
```cpp
60+
class Solution {
61+
public:
62+
// Return the Kth smallest element in the given BST
63+
int KthSmallestElement(Node *root, int k) {
64+
Node* current = root;
65+
int count = 0;
66+
int element = -1;
67+
68+
while(current != NULL){
69+
if(current -> left == NULL){
70+
count++;
71+
if(count == k) element = current -> data;
72+
current = current -> right;
73+
}else{
74+
Node* predecessor = current -> left;
75+
while(predecessor -> right != NULL && predecessor -> right != current){
76+
predecessor = predecessor -> right;
77+
}
78+
79+
if(predecessor -> right == NULL){
80+
predecessor -> right = current;
81+
current = current -> left;
82+
}else{
83+
predecessor -> right = NULL;
84+
count++;
85+
if(count == k) element = current -> data;
86+
current = current -> right;
87+
}
88+
}
89+
if(element != -1) break;
90+
}
91+
92+
93+
return element;
94+
}
95+
};
96+
```
97+
98+
## Problem Solution Explanation
99+
100+
Here's a line-by-line explanation of the solution:
101+
102+
```cpp
103+
class Solution {
104+
public:
105+
// Function to return the Kth smallest element in a BST.
106+
int KthSmallestElement(Node *root, int k) {
107+
```
108+
109+
- **Line 1-4**: We define a class `Solution` with a public method `KthSmallestElement` that takes a pointer to the root node of a BST and an integer `k` as inputs.
110+
- **Purpose**: This function will return the Kth smallest element in the BST.
111+
- **Input**:
112+
- `root`: Pointer to the root of the BST.
113+
- `k`: The position (1-indexed) of the smallest element we want to find.
114+
115+
---
116+
117+
```cpp
118+
Node* current = root; // Start from the root node.
119+
int count = 0; // To keep track of the visited nodes.
120+
int element = -1; // To store the Kth smallest element.
121+
```
122+
123+
- **Line 6-8**: We initialize three variables:
124+
- `current`: Starts at the root node and will be used to traverse the tree.
125+
- `count`: Keeps track of the number of nodes visited so far.
126+
- `element`: Stores the Kth smallest element once found; initialized to `-1` as a default value.
127+
128+
---
129+
130+
```cpp
131+
while(current != NULL) {
132+
```
133+
134+
- **Line 10**: This `while` loop runs as long as `current` is not `NULL`, meaning there are still nodes to process in the BST.
135+
- **Purpose**: This loop allows us to traverse all nodes in the BST using Morris Traversal.
136+
137+
---
138+
139+
```cpp
140+
if(current->left == NULL) {
141+
```
142+
143+
- **Line 12**: We check if the current node has a left child.
144+
- **Case 1**: If `current->left` is `NULL`, it means there are no nodes smaller than `current` in the left subtree. So, we can visit `current` directly.
145+
146+
---
147+
148+
```cpp
149+
count++; // Increment the count of visited nodes.
150+
if(count == k) element = current->data; // Check if this is the Kth node.
151+
current = current->right; // Move to the right child.
152+
```
153+
154+
- **Line 13-15**: If `current->left` is `NULL`, we:
155+
- Increment `count` since we are "visiting" this node.
156+
- Check if `count` equals `k`. If it does, we have found the Kth smallest element, so we set `element = current->data`.
157+
- Move `current` to its right child, continuing the in-order traversal.
158+
159+
#### Example (for Case 1):
160+
If the current node is `3` and `k = 2`, after visiting the first node (say `2`), `count` is incremented to `2`, which matches `k`. So, `element` is set to `3`.
161+
162+
---
163+
164+
```cpp
165+
} else {
166+
```
167+
168+
- **Line 16**: If `current->left` is not `NULL`, then we need to find the in-order predecessor of `current`.
169+
- **Purpose**: The in-order predecessor will allow us to establish a temporary link back to `current` so that we can return to it after visiting the left subtree.
170+
171+
---
172+
173+
```cpp
174+
Node* predecessor = current->left;
175+
while(predecessor->right != NULL && predecessor->right != current) {
176+
predecessor = predecessor->right; // Move to the rightmost node of the left subtree.
177+
}
178+
```
179+
180+
- **Line 17-19**: We set `predecessor` to `current->left` (the left child of `current`) and look for the **rightmost node in the left subtree**.
181+
- **Why the rightmost node?**: The rightmost node is the last node visited in the left subtree in an in-order traversal. By establishing a link back to `current`, we can return to `current` after completing the left subtree traversal.
182+
183+
---
184+
185+
```cpp
186+
if(predecessor->right == NULL) {
187+
predecessor->right = current; // Make the current node the right child of its predecessor.
188+
current = current->left; // Move to the left child of the current node.
189+
```
190+
191+
- **Line 21-23**: If `predecessor->right` is `NULL`, it means we haven't visited the left subtree yet:
192+
- **Step 1**: Set `predecessor->right = current`. This temporary link allows us to come back to `current` after visiting the left subtree.
193+
- **Step 2**: Move `current` to `current->left` to continue traversing the left subtree.
194+
195+
#### Example:
196+
For a node `5` with a left child `3` and a right child `7`, the predecessor of `5` would be `4` (rightmost node in the left subtree). We make `4->right = 5`, allowing us to return to `5` after visiting nodes `2`, `3`, and `4`.
197+
198+
---
199+
200+
```cpp
201+
} else {
202+
predecessor->right = NULL; // Break the temporary link.
203+
count++; // Visit the current node.
204+
if(count == k) element = current->data; // Check if it's the Kth smallest element.
205+
current = current->right; // Move to the right child.
206+
}
207+
```
208+
209+
- **Line 24-28**: If `predecessor->right == current`, it means we've finished visiting the left subtree, so:
210+
- **Step 1**: Set `predecessor->right = NULL` to break the temporary link.
211+
- **Step 2**: Increment `count` since we are "visiting" `current`.
212+
- **Step 3**: Check if `count == k`. If true, `element` is set to `current->data`, which is the Kth smallest element.
213+
- **Step 4**: Move `current` to `current->right`, completing the in-order traversal of `current`.
214+
215+
---
216+
217+
```cpp
218+
if(element != -1) break;
219+
```
220+
221+
- **Line 29**: After finding the Kth smallest element (`element`), we exit the loop early.
222+
223+
---
224+
225+
```cpp
226+
return element; // Return the Kth smallest element.
227+
}
228+
};
229+
```
230+
231+
- **Line 31**: Finally, return the `element` found, which is the Kth smallest in the BST. If `k` is larger than the number of nodes, `element` will remain `-1`, indicating an invalid input.
232+
233+
---
234+
235+
### Example Walkthrough
236+
237+
Consider this BST with `k = 3`:
238+
239+
```
240+
5
241+
/ \
242+
3 7
243+
/ \
244+
2 4
245+
```
246+
247+
1. **Visit Node 5**:
248+
- `current = 5`, `predecessor = 4` (rightmost node of left subtree).
249+
- Set `4->right = 5`.
250+
- Move `current = 3`.
251+
252+
2. **Visit Node 3**:
253+
- `current = 3`, `predecessor = 2` (rightmost node of left subtree).
254+
- Set `2->right = 3`.
255+
- Move `current = 2`.
256+
257+
3. **Visit Node 2**:
258+
- `current = 2` (no left child).
259+
- `count = 1`, move `current = 3` (via temporary link).
260+
261+
4. **Return to Node 3**:
262+
- Break link `2->right`.
263+
- `count = 2`, move `current = 4`.
264+
265+
5. **Visit Node 4**:
266+
- `count = 3` (equals `k`), so `element = 4`.
267+
- Exit loop.
268+
269+
### Complexity Analysis
270+
271+
- **Time Complexity**: `O(N)` since we visit each node at most twice.
272+
- **Space Complexity**: `O(1)` due to the in-place traversal without using a stack or recursion.
273+
274+
### Additional Tips
275+
276+
- **Error Handling**: Ensure `k` is valid by adding boundary checks.
277+
- **Efficiency**: Morris Traversal is optimal for this type of problem since it uses `O(1)` space and provides an in-order sequence of elements.
278+
279+
This solution ensures that we efficiently find the Kth smallest element while maintaining low space complexity by modifying the tree's pointers temporarily.

0 commit comments

Comments
 (0)