๐ข How Do I Find the k-th Smallest Element in an Unsorted Array?
๐ Introduction
Finding the k-th smallest element in an unsorted array is a very common problem in data structures and algorithms. This is one of the favorite questions in coding interviews, competitive programming contests, and technical exams. It also has real-world use cases in data analysis, search engines, and statistical calculations.
The problem is: Given an unsorted array of numbers, how do you find the element that would appear in the k-th position if the array was sorted?
๐งฎ Method 1: Sorting the Array
How It Works
The easiest way is to sort the array in ascending order and directly pick the element at index k-1
. This works because once the array is sorted, the k-th smallest element is simply at that position.
Example
Array = [7, 10, 4, 3, 20, 15]
k = 3
Sorted Array = [3, 4, 7, 10, 15, 20]
3rd smallest element = 7
โ
Python Example:
def kth_smallest_sort(arr, k):
arr.sort()
return arr[k-1]
print(kth_smallest_sort([7, 10, 4, 3, 20, 15], 3)) # Output: 7
Pros and Cons
โ
Very simple and easy to understand.
โ Sorting the entire array takes O(n log n) time, which is not efficient for very large datasets.
๐๏ธ Method 2: Using a Min-Heap
How It Works
A Min-Heap is a binary tree where the smallest element is always at the top (root). By creating a Min-Heap, you can repeatedly remove the smallest element until you reach the k-th one.
Steps
Build a Min-Heap from all array elements.
Remove the smallest element k
times.
The last removed element is the k-th smallest.
Example
Array = [7, 10, 4, 3, 20, 15]
, k = 3
Min-Heap built โ Root = 3.
1st extraction = 3, 2nd = 4, 3rd = 7.
Answer = 7
. โ
Python Example:
import heapq
def kth_smallest_minheap(arr, k):
heapq.heapify(arr)
smallest = None
for _ in range(k):
smallest = heapq.heappop(arr)
return smallest
print(kth_smallest_minheap([7, 10, 4, 3, 20, 15], 3)) # Output: 7
Pros and Cons
โ
Efficient when k
is small compared to n
.
โ Slightly more complex to implement than sorting.
โฑ๏ธ Time Complexity: O(n + k log n).
๐๏ธ Method 3: Using a Max-Heap of Size k
How It Works
Instead of keeping all elements, we only maintain a Max-Heap of size k. The largest element in the heap is compared with incoming elements. If a smaller element is found, it replaces the largest one.
Steps
Insert the first k elements into a Max-Heap.
For each remaining element:
After processing all elements, the root of the Max-Heap is the k-th smallest.
Example
Array = [7, 10, 4, 3, 20, 15]
, k = 3
Initial heap = [7, 10, 4]
(Max = 10).
Next element = 3 โ Replaces 10 โ Heap = [7, 3, 4]
.
Next = 20 โ Ignored.
Next = 15 โ Ignored.
Root = 7
. โ
Python Example:
import heapq
def kth_smallest_maxheap(arr, k):
max_heap = [-x for x in arr[:k]]
heapq.heapify(max_heap)
for num in arr[k:]:
if -num > max_heap[0]:
heapq.heapreplace(max_heap, -num)
return -max_heap[0]
print(kth_smallest_maxheap([7, 10, 4, 3, 20, 15], 3)) # Output: 7
Pros and Cons
โ
More memory-efficient since only k elements are stored.
โ
Works well when n is very large but k is relatively small.
โฑ๏ธ Time Complexity: O(k + (n-k) log k).
โก Method 4: Quickselect Algorithm
How It Works
Quickselect is based on the partition process of Quicksort. Instead of sorting the entire array, it repeatedly partitions the array around a pivot until the pivot lands at the k-th position.
Steps
Choose a pivot element.
Partition array into smaller and larger than pivot.
If pivot index = k-1 โ return pivot.
If pivot index > k-1 โ search left.
Else โ search right.
Example
Array = [7, 10, 4, 3, 20, 15]
, k = 3.
Pivot = 7 โ Partition = [4, 3] [7] [10, 20, 15]
.
Pivot index = 2 โ which is k-1 = 2 โ Answer = 7
. โ
Python Example:
def partition(arr, low, high):
pivot = arr[high]
i = low
for j in range(low, high):
if arr[j] <= pivot:
arr[i], arr[j] = arr[j], arr[i]
i += 1
arr[i], arr[high] = arr[high], arr[i]
return i
def quickselect(arr, low, high, k):
if low <= high:
pivot_index = partition(arr, low, high)
if pivot_index == k:
return arr[pivot_index]
elif pivot_index > k:
return quickselect(arr, low, pivot_index - 1, k)
else:
return quickselect(arr, pivot_index + 1, high, k)
arr = [7, 10, 4, 3, 20, 15]
k = 3
print(quickselect(arr, 0, len(arr) - 1, k - 1)) # Output: 7
Pros and Cons
โ
Very efficient in practice with average O(n) time.
โ Worst case can go up to O(nยฒ) if poor pivots are chosen.
Often used in interview problems due to efficiency.
๐ Comparison of All Methods
Method | Time Complexity | Best Use Case |
---|
Sorting | O(n log n) | Small arrays or when simplicity is key |
Min-Heap | O(n + k log n) | When k is small compared to n |
Max-Heap of size k | O(k + (n-k) log k) | Large n, small k |
Quickselect | O(n) average, O(nยฒ) worst | Large datasets, efficient solutions |
๐ Summary
Finding the k-th smallest element in an unsorted array can be solved in multiple ways depending on your needs. If you just want something simple, sorting works fine. If you want efficiency for large datasets, heaps and the Quickselect algorithm are better options. Quickselect is often the fastest in practice, but heaps provide stable performance when k is small.