|
| 1 | +<h1 align='center'>Kth - Smallest</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | +**Problem URL :** [Kth Smallest](https://www.geeksforgeeks.org/problems/kth-smallest-element5635/1?itm_source=geeksforgeeks&itm_medium=article&itm_campaign=practice_card) |
| 5 | + |
| 6 | + |
| 7 | + |
| 8 | +## Problem Explanation |
| 9 | + |
| 10 | +The **Kth Smallest Element** problem requires us to find the `k`th smallest element in a given array. This is commonly encountered in coding interviews and is essential for learning how to handle selection problems in an array efficiently. |
| 11 | + |
| 12 | +Let's break down what it means with an example: |
| 13 | +1. **Input**: We have an unsorted array `arr = [7, 10, 4, 3, 20, 15]` and we want to find the 3rd smallest element (`k = 3`). |
| 14 | +2. **Output**: The 3rd smallest element in this array is `7`, because if we sorted the array, we would get `[3, 4, 7, 10, 15, 20]`. |
| 15 | + |
| 16 | +To solve this, the naive approach would be to sort the entire array and pick the `k`th element directly, but that could take time `O(n log n)` where `n` is the size of the array. However, we can use a more efficient solution using a **Max Heap** (or priority queue), which allows us to only keep track of the smallest `k` elements without fully sorting the array. |
| 17 | + |
| 18 | +### Approach to Solve the Problem |
| 19 | + |
| 20 | +1. **Max Heap Initialization**: |
| 21 | + - We initialize a **Max Heap** to store the smallest `k` elements seen so far. This is done because, in a Max Heap, the largest element among the smallest `k` elements will always be at the top. |
| 22 | + - In C++, the `priority_queue<int>` by default is a Max Heap. |
| 23 | + |
| 24 | +2. **First `k` Elements**: |
| 25 | + - Push the first `k` elements of `arr` into the heap. After adding these `k` elements, the root of the heap (i.e., `pq.top()`) will contain the largest element among the first `k` elements. |
| 26 | + |
| 27 | +3. **Traverse Remaining Elements**: |
| 28 | + - For each element from the `k+1`th element onwards: |
| 29 | + - If this element is smaller than the top of the Max Heap, remove the top element and insert the current element. |
| 30 | + - This step ensures that we always maintain only the `k` smallest elements in the heap, with the largest of them at the root. |
| 31 | + |
| 32 | +4. **Result**: |
| 33 | + - Once all elements have been processed, the top of the Max Heap will contain the `k`th smallest element in the array. |
| 34 | + |
| 35 | +## Problem Solution |
| 36 | +```cpp |
| 37 | +class Solution { |
| 38 | + public: |
| 39 | + // arr : given array |
| 40 | + // k : find kth smallest element and return using this function |
| 41 | + int kthSmallest(vector<int> &arr, int k) { |
| 42 | + priority_queue<int> pq; |
| 43 | + |
| 44 | + for(int i = 0; i < k; i++){ |
| 45 | + pq.push(arr[i]); |
| 46 | + } |
| 47 | + |
| 48 | + for(int i = k; i < arr.size(); i++){ |
| 49 | + if(arr[i] < pq.top()){ |
| 50 | + pq.pop(); |
| 51 | + pq.push(arr[i]); |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + return pq.top(); |
| 56 | + } |
| 57 | +}; |
| 58 | +``` |
| 59 | +
|
| 60 | +## Problem Solution Explanation |
| 61 | +Here's a line-by-line breakdown of the code, including explanations for each part with examples. |
| 62 | +
|
| 63 | +```cpp |
| 64 | +class Solution { |
| 65 | + public: |
| 66 | + // arr : given array |
| 67 | + // k : find kth smallest element and return using this function |
| 68 | + int kthSmallest(vector<int> &arr, int k) { |
| 69 | +``` |
| 70 | + |
| 71 | +- We define a class `Solution` with a public method `kthSmallest`. |
| 72 | +- The method takes a reference to a vector `arr` (our input array) and an integer `k`, representing the position of the smallest element we want to find. |
| 73 | +- **Example**: If `arr = [7, 10, 4, 3, 20, 15]` and `k = 3`, our goal is to find the 3rd smallest element. |
| 74 | + |
| 75 | +```cpp |
| 76 | + priority_queue<int> pq; |
| 77 | +``` |
| 78 | + |
| 79 | +- Here, we declare a max-heap `pq` using `priority_queue<int>` in C++. By default, `priority_queue` in C++ is a max-heap, which means the largest element will always be at the top. |
| 80 | +- This max-heap will help us keep track of the `k` smallest elements in the array. |
| 81 | +- **Example**: Initially, the max-heap is empty: `pq = {}`. |
| 82 | + |
| 83 | +```cpp |
| 84 | + for(int i = 0; i < k; i++){ |
| 85 | + pq.push(arr[i]); |
| 86 | + } |
| 87 | +``` |
| 88 | +
|
| 89 | +- We push the first `k` elements of `arr` into the max-heap. |
| 90 | +- After this loop, the heap `pq` will contain the first `k` elements of `arr`, with the largest of these elements at the root/top of the heap. |
| 91 | +- **Example**: If `arr = [7, 10, 4, 3, 20, 15]` and `k = 3`, after this loop, the heap contains `{10, 7, 4}`, with `10` as the largest element at the top. |
| 92 | +
|
| 93 | +```cpp |
| 94 | + for(int i = k; i < arr.size(); i++){ |
| 95 | + if(arr[i] < pq.top()){ |
| 96 | + pq.pop(); |
| 97 | + pq.push(arr[i]); |
| 98 | + } |
| 99 | + } |
| 100 | +``` |
| 101 | + |
| 102 | +- Now we iterate over the rest of the array, starting from index `k`. |
| 103 | + - `arr[i] < pq.top()`: We check if the current element of `arr` is smaller than the largest element in our heap (`pq.top()`). |
| 104 | + - If it is smaller, we pop the largest element from the heap (remove the root) and push the current element. This step ensures that we maintain only the `k` smallest elements in `pq`, with the largest of those `k` elements at the top. |
| 105 | + - If the current element is not smaller, we ignore it and move to the next one. |
| 106 | +- **Example**: |
| 107 | + - Let’s continue with `arr = [7, 10, 4, 3, 20, 15]` and `k = 3`. |
| 108 | + - Initially, `pq = {10, 7, 4}`. |
| 109 | + - For `arr[3] = 3`: `3 < 10` (top of heap), so we pop `10` and push `3`. Now, `pq = {7, 4, 3}`. |
| 110 | + - For `arr[4] = 20`: `20 > 7` (top of heap), so we ignore it. |
| 111 | + - For `arr[5] = 15`: `15 > 7` (top of heap), so we ignore it. |
| 112 | + |
| 113 | +```cpp |
| 114 | + return pq.top(); |
| 115 | + } |
| 116 | +}; |
| 117 | +``` |
| 118 | + |
| 119 | +- After processing all elements, the top of the heap (`pq.top()`) holds the `k`th smallest element. |
| 120 | +- **Example**: In our example, `pq.top()` is `7`, so `7` is the 3rd smallest element in `arr = [7, 10, 4, 3, 20, 15]`. |
| 121 | + |
| 122 | +### Full Example Walkthrough |
| 123 | + |
| 124 | +For `arr = [7, 10, 4, 3, 20, 15]` and `k = 3`: |
| 125 | +1. **Initialize Heap**: |
| 126 | + - Insert first `k` elements `[7, 10, 4]` into `pq`. |
| 127 | + - `pq = {10, 7, 4}`, with `10` as the max (top of heap). |
| 128 | + |
| 129 | +2. **Process Remaining Elements**: |
| 130 | + - `3 < 10`: Pop `10`, push `3` → `pq = {7, 4, 3}`. |
| 131 | + - `20 > 7`: Ignore it. |
| 132 | + - `15 > 7`: Ignore it. |
| 133 | + |
| 134 | +3. **Result**: |
| 135 | + - `pq.top()` is `7`, which is the 3rd smallest element in `arr`. |
| 136 | + |
| 137 | +### Step 4: Time and Space Complexity |
| 138 | + |
| 139 | +1. **Time Complexity**: |
| 140 | + - Building the initial Max Heap with `k` elements takes `O(k log k)`. |
| 141 | + - For the remaining `n - k` elements, each comparison and insertion takes `O(log k)`, leading to an overall complexity of `O(k log k) + O((n - k) log k)`, which simplifies to `O(n log k)`. |
| 142 | + |
| 143 | +2. **Space Complexity**: |
| 144 | + - The space complexity is `O(k)` due to the Max Heap storing up to `k` elements. |
| 145 | + |
| 146 | +### Step 5: Additional Recommendations for Students |
| 147 | + |
| 148 | +- **Heap Fundamentals**: Understanding how heaps work and when to use Max vs. Min Heaps is critical for similar problems. |
| 149 | +- **Edge Cases**: Consider cases where `k` is `1` (smallest element) or equal to the array's length (largest element). |
| 150 | +- **Alternative Approaches**: For large values of `k`, a Min Heap might be a better choice, or use quickselect for linear-time average solutions. |
| 151 | + |
| 152 | +This approach using a Max Heap is efficient and aligns well with real-world problem-solving needs where we handle partial sorts frequently. |
0 commit comments