Data Structures and Algorithms (DSA)  

How Do I Find the k-th Smallest Element in an Unsorted Array?

๐Ÿ”ข 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

  1. Build a Min-Heap from all array elements.

  2. Remove the smallest element k times.

  3. 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

  1. Insert the first k elements into a Max-Heap.

  2. For each remaining element:

    • If itโ€™s smaller than the largest (root of the heap), replace it.

  3. 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

  1. Choose a pivot element.

  2. Partition array into smaller and larger than pivot.

  3. If pivot index = k-1 โ†’ return pivot.

  4. If pivot index > k-1 โ†’ search left.

  5. 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

MethodTime ComplexityBest Use Case
SortingO(n log n)Small arrays or when simplicity is key
Min-HeapO(n + k log n)When k is small compared to n
Max-Heap of size kO(k + (n-k) log k)Large n, small k
QuickselectO(n) average, O(nยฒ) worstLarge 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.