K’th Smallest/Largest Element in Unsorted Array | Expected Linear Time (original) (raw)

Last Updated : 23 Jul, 2025

Given an array of distinct integers and an integer k, where k is smaller than the array's size, the task is to find the k'th smallest element in the array.

**Examples:

**Input: arr = [7, 10, 4, 3, 20, 15], k = 3
**Output: 7
**Explanation: The sorted array is [3, 4, 7, 10, 15, 20], so the 3rd smallest element is 7.

**Input: arr = [7, 10, 4, 3, 20, 15], k = 4
**Output: 10
**Explanation: The sorted array is [3, 4, 7, 10, 15, 20], so the 4th smallest element is 10.

Try It Yourselfredirect icon

Please note that there are multiple ways to solve this problem discussed in kth-Smallest/Largest Element in Unsorted Array. The solution discussed here works best in practice.

The idea is to use a randomized pivot selection to partition the array, reducing the search space by focusing on the subarray where the k'th element must lie.

Step by step approach:

**Choose a Random Pivot: Randomly select an element as the pivot. This helps avoid the worst-case scenario in some cases (like when the array is already sorted).
**Partitioning: Rearrange the array such that all elements less than the pivot are on the left side, and those greater than the pivot are on the right side.
**Recursive Search: Once the pivot is positioned, if its index equals n-k _comparison , then it’s the Kth largest element. If not, recursively search the appropriate partition (left or right) based on the with n-k.

C++ `

// C++ program to find K’th Smallest/ // Largest Element in Unsorted Array #include<bits/stdc++.h> using namespace std;

// Partition function: Rearranges elements // around a pivot (last element) int partition(vector &arr, int l, int r) {
int x = arr[r];
int i = l;

// Iterate through the subarray
for (int j = l; j <= r - 1; j++) {  
    
    // Move elements <= pivot to the 
    // left partition
    if (arr[j] <= x) {  
        swap(arr[i], arr[j]);  
        i++; 
    }  
}  

// Place the pivot in its correct position
swap(arr[i], arr[r]);  
return i;  

}

// Randomizes the pivot to avoid worst-case performance int randomPartition(vector &arr, int l, int r) {
int n = r - l + 1;
int pivot = rand() % n;
swap(arr[l + pivot], arr[r]); return partition(arr, l, r); }

// function to find the k'th smallest element // using QuickSelect int quickSelect(vector &arr, int l, int r, int k) {

// Check if k is within the valid range 
// of the current subarray
if (k > 0 && k <= r - l + 1) {  
    
    // Partition the array and get the
    // pivot's final position
    int pos = randomPartition(arr, l, r);  

    // If pivot is the k'th element, return it
    if (pos - l == k - 1)  
        return arr[pos];  

    // If pivot's position is larger than k, 
    // search left subarray
    if (pos - l > k - 1)  
        return quickSelect(arr, l, pos - 1, k);  

    // Otherwise, search right subarray and adjust k 
    // (k is reduced by the size of the left partition)
    return quickSelect(arr, pos + 1, r, k - (pos - l + 1));  
}  

// Return infinity for invalid k (error handling)
return INT_MAX;  

}

int kthSmallest(vector &arr, int k) { int n = arr.size();

return quickSelect(arr, 0, n-1, k);

}

int main() {
vector arr = {12, 3, 5, 7, 4, 19, 26};
int k = 3;
cout << kthSmallest(arr, k);
return 0;
}

Java

// Java program to find K’th Smallest/ // Largest Element in Unsorted Array import java.util.Random;

class GfG {

// Partition function: Rearranges elements 
// around a pivot (last element)
static int partition(int[] arr, int l, int r) {  
    int x = arr[r];  
    int i = l;     

    // Iterate through the subarray
    for (int j = l; j <= r - 1; j++) {  
        
        // Move elements <= pivot to the left partition
        if (arr[j] <= x) {  
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++; 
        }  
    }  
    
    // Place the pivot in its correct position
    int temp = arr[i];
    arr[i] = arr[r];
    arr[r] = temp;
    return i;  
}  

// Randomizes the pivot to avoid worst-case performance
static int randomPartition(int[] arr, int l, int r) {  
    Random rand = new Random();
    int n = r - l + 1;  
    int pivot = rand.nextInt(n);      
    int temp = arr[l + pivot];
    arr[l + pivot] = arr[r];
    arr[r] = temp;
    return partition(arr, l, r); 
}  

// function to find the k'th smallest element using QuickSelect
static int quickSelect(int[] arr, int l, int r, int k) {  
    
    // Check if k is within the valid range of 
    // the current subarray
    if (k > 0 && k <= r - l + 1) {  
        
        // Partition the array and get the
        // pivot's final position
        int pos = randomPartition(arr, l, r);  

        // If pivot is the k'th element, return it
        if (pos - l == k - 1)  
            return arr[pos];  

        // If pivot's position is larger than k,
        // search left subarray
        if (pos - l > k - 1)  
            return quickSelect(arr, l, pos - 1, k);  

        // Otherwise, search right subarray and adjust k 
        // (k is reduced by the size of the left partition)
        return quickSelect(arr, pos + 1, r, k - (pos - l + 1));  
    }  
    
    // Return infinity for invalid k (error handling)
    return Integer.MAX_VALUE;  
}

static int kthSmallest(int[] arr, int k) {
    int n = arr.length;
    return quickSelect(arr, 0, n - 1, k);
}

public static void main(String[] args) {  
    int[] arr = {12, 3, 5, 7, 4, 19, 26};  
    int k = 3;  
    System.out.println(kthSmallest(arr, k));  
}  

}

Python

Python program to find K’th Smallest/

Largest Element in Unsorted Array

import random

Partition function: Rearranges elements

around a pivot (last element)

def partition(arr, l, r):
x = arr[r]
i = l

# Iterate through the subarray
for j in range(l, r):  
    
    # Move elements <= pivot to the left partition
    if arr[j] <= x:  
        arr[i], arr[j] = arr[j], arr[i]  
        i += 1  
    
# Place the pivot in its correct position
arr[i], arr[r] = arr[r], arr[i]  
return i  

Randomizes the pivot to avoid worst-case performance

def randomPartition(arr, l, r):
n = r - l + 1
pivot = random.randint(0, n - 1)
arr[l + pivot], arr[r] = arr[r], arr[l + pivot]
return partition(arr, l, r)

function to find the k'th smallest element using QuickSelect

def quickSelect(arr, l, r, k):

# Check if k is within the valid range of the current subarray
if 0 < k <= r - l + 1:  
    
    # Partition the array and get the pivot's final position
    pos = randomPartition(arr, l, r)  

    # If pivot is the k'th element, return it
    if pos - l == k - 1:  
        return arr[pos]  

    # If pivot's position is larger than k, search left subarray
    if pos - l > k - 1:  
        return quickSelect(arr, l, pos - 1, k)  

    # Otherwise, search right subarray and adjust k 
    # (k is reduced by the size of the left partition)
    return quickSelect(arr, pos + 1, r, k - (pos - l + 1))  

# Return infinity for invalid k (error handling)
return float('inf')  

def kthSmallest(arr, k): n = len(arr) return quickSelect(arr, 0, n - 1, k)

if name == "main": arr = [12, 3, 5, 7, 4, 19, 26]
k = 3
print(kthSmallest(arr, k))

C#

// C# program to find K’th Smallest/ // Largest Element in Unsorted Array using System;

class GfG {

// Partition function: Rearranges elements 
// around a pivot (last element)
static int partition(int[] arr, int l, int r) {  
    int x = arr[r];  
    int i = l;     

    // Iterate through the subarray
    for (int j = l; j <= r - 1; j++) {  
        
        // Move elements <= pivot to the left partition
        if (arr[j] <= x) {  
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++; 
        }  
    }  
    
    // Place the pivot in its correct position
    int temp2 = arr[i];
    arr[i] = arr[r];
    arr[r] = temp2;
    return i;  
}  

// Randomizes the pivot to avoid worst-case performance
static int randomPartition(int[] arr, int l, int r) {  
    Random rand = new Random();
    int n = r - l + 1;  
    int pivot = rand.Next(n);      
    int temp = arr[l + pivot];
    arr[l + pivot] = arr[r];
    arr[r] = temp;
    return partition(arr, l, r); 
}  

// function to find the k'th smallest element using QuickSelect
static int quickSelect(int[] arr, int l, int r, int k) {  
    
    // Check if k is within the valid range of the
    // current subarray
    if (k > 0 && k <= r - l + 1) {  
        
        // Partition the array and get the pivot's
        // final position
        int pos = randomPartition(arr, l, r);  

        // If pivot is the k'th element, return it
        if (pos - l == k - 1)  
            return arr[pos];  

        // If pivot's position is larger than k, search
        // left subarray
        if (pos - l > k - 1)  
            return quickSelect(arr, l, pos - 1, k);  

        // Otherwise, search right subarray and adjust k 
        // (k is reduced by the size of the left partition)
        return quickSelect(arr, pos + 1, r, k - (pos - l + 1));  
    }  
    
    // Return infinity for invalid k (error handling)
    return int.MaxValue;  
}

static int kthSmallest(int[] arr, int k) {
    int n = arr.Length;
    return quickSelect(arr, 0, n - 1, k);
}

static void Main() {  
    int[] arr = {12, 3, 5, 7, 4, 19, 26};  
    int k = 3;  
    Console.WriteLine(kthSmallest(arr, k));  
}  

}

JavaScript

// JavaScript program to find K’th Smallest/ // Largest Element in Unsorted Array

// Partition function: Rearranges elements // around a pivot (last element) function partition(arr, l, r) {
let x = arr[r];
let i = l;

// Iterate through the subarray
for (let j = l; j <= r - 1; j++) {  
    
    // Move elements <= pivot to the left partition
    if (arr[j] <= x) {  
        [arr[i], arr[j]] = [arr[j], arr[i]];  
        i++; 
    }  
}  

// Place the pivot in its correct position
[arr[i], arr[r]] = [arr[r], arr[i]];  
return i;  

}

// Randomizes the pivot to avoid worst-case performance function randomPartition(arr, l, r) {
let n = r - l + 1;
let pivot = Math.floor(Math.random() * n);
[arr[l + pivot], arr[r]] = [arr[r], arr[l + pivot]]; return partition(arr, l, r); }

// function to find the k'th smallest element using QuickSelect function quickSelect(arr, l, r, k) {
// Check if k is within the valid range of the current subarray if (k > 0 && k <= r - l + 1) {

    // Partition the array and get the pivot's final position
    let pos = randomPartition(arr, l, r);  

    // If pivot is the k'th element, return it
    if (pos - l == k - 1)  
        return arr[pos];  

    // If pivot's position is larger than k, search left subarray
    if (pos - l > k - 1)  
        return quickSelect(arr, l, pos - 1, k);  

    // Otherwise, search right subarray and adjust k 
    // (k is reduced by the size of the left partition)
    return quickSelect(arr, pos + 1, r, k - (pos - l + 1));  
}  

// Return Infinity for invalid k (error handling)
return Infinity;  

}

function kthSmallest(arr, k) { let n = arr.length; return quickSelect(arr, 0, n - 1, k); }

let arr = [12, 3, 5, 7, 4, 19, 26];
let k = 3;
console.log(kthSmallest(arr, k));

`

**Time Complexity: O(n) The worst-case time complexity of the above solution is still O(n2). In the worst case, the randomized function may always pick a corner element. However, the average-case time complexity is O(n). The assumption in the analysis is, random number generator is equally likely to generate any number in the input range.
**Auxiliary Space: **O(1) since using constant variables.

**Even if the worst case time complexity is quadratic, this solution works best in practice.