Program to find kth smallest element in linear time in Python

Finding the kth smallest element in a list is a common problem that can be solved efficiently using heap data structures. The challenge is to achieve O(n) average time complexity rather than the naive O(n log n) sorting approach.

So, if the input is like nums = [6, 4, 9, 3, 1] and k = 2, then the output will be 4. After sorting, the list becomes [1, 3, 4, 6, 9], where the 2nd smallest element (0-indexed) is 4.

Algorithm Steps

To solve this efficiently, we will follow these steps ?

  • Create a max heap to store the k+1 smallest elements
  • Insert the first k+1 elements into the max heap
  • For remaining elements, if an element is smaller than the heap's maximum, replace the maximum with this element
  • The root of the heap will be the kth smallest element

Implementation Using Max Heap

Python's heapq module provides a min heap, so we use negative values to simulate a max heap ?

from heapq import heappop, heappush

def solve(nums, k):
    max_heap = []
    
    # Insert first k+1 elements into max heap
    for i in range(k + 1):
        heappush(max_heap, -nums[i])
    
    # Process remaining elements
    for i in range(k + 1, len(nums)):
        if nums[i] < -max_heap[0]:  # If current element is smaller than heap's max
            heappop(max_heap)       # Remove the maximum
            heappush(max_heap, -nums[i])  # Insert current element
    
    return -max_heap[0]  # Return the kth smallest

# Test the function
nums = [6, 4, 9, 3, 1]
k = 2
result = solve(nums, k)
print(f"The {k}th smallest element is: {result}")
The 2th smallest element is: 4

How It Works

The algorithm maintains a max heap of size k+1. At any point, this heap contains the k+1 smallest elements seen so far. When we encounter a smaller element, we remove the largest from the heap and add the new element. This ensures the heap always contains the k+1 smallest elements.

Alternative: Using Quickselect Algorithm

For true O(n) average time complexity, we can use the Quickselect algorithm ?

import random

def quickselect(nums, k):
    def partition(left, right, pivot_idx):
        pivot_value = nums[pivot_idx]
        # Move pivot to end
        nums[pivot_idx], nums[right] = nums[right], nums[pivot_idx]
        
        store_idx = left
        for i in range(left, right):
            if nums[i] < pivot_value:
                nums[store_idx], nums[i] = nums[i], nums[store_idx]
                store_idx += 1
        
        # Move pivot to final position
        nums[right], nums[store_idx] = nums[store_idx], nums[right]
        return store_idx
    
    def select(left, right, k):
        if left == right:
            return nums[left]
        
        # Choose random pivot
        pivot_idx = random.randint(left, right)
        pivot_idx = partition(left, right, pivot_idx)
        
        if k == pivot_idx:
            return nums[k]
        elif k < pivot_idx:
            return select(left, pivot_idx - 1, k)
        else:
            return select(pivot_idx + 1, right, k)
    
    return select(0, len(nums) - 1, k)

# Test the quickselect approach
nums = [6, 4, 9, 3, 1]
k = 2
result = quickselect(nums.copy(), k)  # Use copy to preserve original
print(f"Using Quickselect: {result}")
Using Quickselect: 4

Comparison

Method Time Complexity Space Complexity Best For
Max Heap O(n log k) O(k) Small k values
Quickselect O(n) average O(1) True linear time
Sorting O(n log n) O(1) Multiple queries

Conclusion

For finding the kth smallest element, use the heap approach when k is small, or Quickselect for guaranteed O(n) average performance. The heap method is more predictable, while Quickselect offers better theoretical complexity.

Updated on: 2026-03-26T17:31:22+05:30

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements