K’th Smallest/Largest Element in Unsorted Array | Expected Linear Time
Last Updated :
18 Sep, 2023
Prerequisite: K’th Smallest/Largest Element in Unsorted Array | Set 1
Given an array and a number k where k is smaller than the size of the array, we need to find the k’th smallest element in the given array. It is given that all array elements are distinct.
Examples:
Input: arr[] = {7, 10, 4, 3, 20, 15}
k = 3
Output: 7
Input: arr[] = {7, 10, 4, 3, 20, 15}
k = 4
Output: 10
We have discussed three different solutions here.
Approach 1:
- Select a random element from an array as a pivot.
- Then partition to the array around the pivot, its help to all the smaller elements were placed before the pivot and all greater elements are placed after the pivot.
- then Check the position of the pivot. If it is the kth element then return it.
- If it is less than the kth element then repeat the process of the subarray.
- If it is greater than the kth element then repeat the process of the left subarray.
That Algorithm is the QuickSelect and It is similar to the QuickSort.
In this post method 5 is discussed which is mainly an extension of method 5 (QuickSelect) discussed in the previous post. The idea is to randomly pick a pivot element. To implement a randomized partition, we use a random function, rand() to generate an index between l and r, swap the element at the randomly generated index with the last element, and finally call the standard partition process which uses the last element as pivot.
Steps to solve the problem:
1. Check if k>0&& k<=r-l+1:
declare pos as randomPartition(arr,l,r).
check if pos-1==k-1 than return arr[pos].
check if pos-1>k-1 than recursively call kthsmallest(arr,l,pos-1,k).
return recursively call kthsmallest(arr,pos+1,r,k-pos+l-1).
2. Return INT_MAX.
Following is an implementation of the above Randomized QuickSelect.
C++
#include<iostream>
#include<climits>
#include<cstdlib>
using namespace std;
int randomPartition( int arr[], int l, int r);
int kthSmallest( int arr[], int l, int r, int k)
{
if (k > 0 && k <= r - l + 1)
{
int pos = randomPartition(arr, l, r);
if (pos-l == k-1)
return arr[pos];
if (pos-l > k-1)
return kthSmallest(arr, l, pos-1, k);
return kthSmallest(arr, pos+1, r, k-pos+l-1);
}
return INT_MAX;
}
void swap( int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int partition( int arr[], int l, int r)
{
int x = arr[r], i = l;
for ( int j = l; j <= r - 1; j++)
{
if (arr[j] <= x)
{
swap(&arr[i], &arr[j]);
i++;
}
}
swap(&arr[i], &arr[r]);
return i;
}
int randomPartition( int 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);
}
int main()
{
int arr[] = {12, 3, 5, 7, 4, 19, 26};
int n = sizeof (arr)/ sizeof (arr[0]), k = 3;
cout << "K'th smallest element is " << kthSmallest(arr, 0, n-1, k);
return 0;
}
|
Java
class KthSmallst
{
int kthSmallest( int arr[], int l, int r, int k)
{
if (k > 0 && k <= r - l + 1 )
{
int pos = randomPartition(arr, l, r);
if (pos-l == k- 1 )
return arr[pos];
if (pos-l > k- 1 )
return kthSmallest(arr, l, pos- 1 , k);
return kthSmallest(arr, pos+ 1 , r, k-pos+l- 1 );
}
return Integer.MAX_VALUE;
}
void swap( int arr[], int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
int partition( int arr[], int l, int r)
{
int x = arr[r], i = l;
for ( int j = l; j < r; j++)
{
if (arr[j] <= x)
{
swap(arr, i, j);
i++;
}
}
swap(arr, i, r);
return i;
}
int randomPartition( int arr[], int l, int r)
{
int n = r - l + 1 ;
int pivot = ( int )(Math.random() * (n - 1 ));
swap(arr, l + pivot, r);
return partition(arr, l, r);
}
public static void main(String args[])
{
KthSmallst ob = new KthSmallst();
int arr[] = { 12 , 3 , 5 , 7 , 4 , 19 , 26 };
int n = arr.length,k = 3 ;
System.out.println( "K'th smallest element is " +
ob.kthSmallest(arr, 0 , n- 1 , k));
}
}
|
Python3
import random
def kthSmallest(arr, l, r, k):
if (k > 0 and k < = r - l + 1 ):
pos = randomPartition(arr, l, r)
if (pos - l = = k - 1 ):
return arr[pos]
if (pos - l > k - 1 ):
return kthSmallest(arr, l, pos - 1 , k)
return kthSmallest(arr, pos + 1 , r,
k - pos + l - 1 )
return 999999999999
def swap(arr, a, b):
temp = arr[a]
arr[a] = arr[b]
arr[b] = temp
def partition(arr, l, r):
x = arr[r]
i = l
for j in range (l, r):
if (arr[j] < = x):
swap(arr, i, j)
i + = 1
swap(arr, i, r)
return i
def randomPartition(arr, l, r):
n = r - l + 1
pivot = int (random.random() * n)
swap(arr, l + pivot, r)
return partition(arr, l, r)
if __name__ = = '__main__' :
arr = [ 12 , 3 , 5 , 7 , 4 , 19 , 26 ]
n = len (arr)
k = 3
print ( "K'th smallest element is" ,
kthSmallest(arr, 0 , n - 1 , k))
|
C#
using System;
class GFG
{
int kthSmallest( int []arr, int l, int r, int k)
{
if (k > 0 && k <= r - l + 1)
{
int pos = randomPartition(arr, l, r);
if (pos-l == k - 1)
return arr[pos];
if (pos - l > k - 1)
return kthSmallest(arr, l, pos - 1, k);
return kthSmallest(arr, pos + 1, r,
k - pos + l - 1);
}
return int .MaxValue;
}
void swap( int []arr, int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
int partition( int []arr, int l, int r)
{
int x = arr[r], i = l;
for ( int j = l; j <= r - 1; j++)
{
if (arr[j] <= x)
{
swap(arr, i, j);
i++;
}
}
swap(arr, i, r);
return i;
}
int randomPartition( int []arr, int l, int r)
{
int n = r - l + 1;
Random rnd = new Random();
int rand = rnd.Next(0, 1);
int pivot = ( int )(rand * (n - 1));
swap(arr, l + pivot, r);
return partition(arr, l, r);
}
public static void Main()
{
GFG ob = new GFG();
int []arr = {12, 3, 5, 7, 4, 19, 26};
int n = arr.Length,k = 3;
Console.Write( "K'th smallest element is " +
ob.kthSmallest(arr, 0, n - 1, k));
}
}
|
PHP
<?php
function kthSmallest( $arr , $l , $r , $k )
{
if ( $k > 0 && $k <= $r - $l + 1)
{
$pos = randomPartition( $arr , $l , $r );
if ( $pos - $l == $k -1)
return $arr [ $pos ];
if ( $pos - $l > $k -1)
return kthSmallest( $arr , $l , $pos -1, $k );
return kthSmallest( $arr , $pos +1, $r ,
$k - $pos + $l -1);
}
return PHP_INT_MAX;
}
function swap( $a , $b )
{
$temp = $a ;
$a = $b ;
$b = $temp ;
}
function partition( $arr , $l , $r )
{
$x = $arr [ $r ];
$i = $l ;
for ( $j = $l ; $j <= $r - 1; $j ++)
{
if ( $arr [ $j ] <= $x )
{
list( $arr [ $i ], $arr [ $j ])= array ( $arr [ $j ], $arr [ $i ]);
$i ++;
}
}
list( $arr [ $i ], $arr [ $r ])= array ( $arr [ $r ], $arr [ $i ]);
return $i ;
}
function randomPartition( $arr , $l , $r )
{
$n = $r - $l +1;
$pivot = rand() % $n ;
list( $arr [ $l + $pivot ], $arr [ $r ]) =
array ( $arr [ $r ], $arr [ $l + $pivot ] );
return partition( $arr , $l , $r );
}
$arr = array (12, 3, 5, 7, 4, 19, 260);
$n = sizeof( $arr )/sizeof( $arr [0]);
$k = 3;
echo "K'th smallest element is " ,
kthSmallest( $arr , 0, $n -1, $k );
?>
|
Javascript
<script>
function kthSmallest(arr,l,r,k)
{
if (k > 0 && k <= r - l + 1)
{
let pos = randomPartition(arr, l, r);
if (pos-l == k-1)
return arr[pos];
if (pos-l > k-1)
return kthSmallest(arr, l, pos-1, k);
return kthSmallest(arr, pos+1, r, k-pos+l-1);
}
return Integer.MAX_VALUE;
}
function swap(arr,i,j)
{
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function partition(arr,l,r)
{
let x = arr[r], i = l;
for (let j = l; j <= r - 1; j++)
{
if (arr[j] <= x)
{
swap(arr, i, j);
i++;
}
}
swap(arr, i, r);
return i;
}
function randomPartition(arr,l,r)
{
let n = r-l+1;
let pivot = Math.floor((Math.random()) * (n-1));
swap(arr, l + pivot, r);
return partition(arr, l, r);
}
let arr=[12, 3, 5, 7, 4, 19, 26];
let n = arr.length,k = 3;
document.write( "K'th smallest element is " +
kthSmallest(arr, 0, n-1, k));
</script>
|
Output
K'th smallest element is 5
Time Complexity: O(n^2)
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. The expected time complexity of the above randomized QuickSelect 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.
Share your thoughts in the comments
Please Login to comment...