Given two sorted arrays of size m and n respectively, you are tasked with finding the element that would be at the k’th position of the final sorted array.
Examples:
Input : Array 1 - 2 3 6 7 9
Array 2 - 1 4 8 10
k = 5
Output : 6
Explanation: The final sorted array would be -
1, 2, 3, 4, 6, 7, 8, 9, 10
The 5th element of this array is 6.
Input : Array 1 - 100 112 256 349 770
Array 2 - 72 86 113 119 265 445 892
k = 7
Output : 256
Explanation: Final sorted array is -
72, 86, 100, 112, 113, 119, 256, 265, 349, 445, 770, 892
7th element of this array is 256.
Basic Approach
Since we are given two sorted arrays, we can use the merging technique to get the final merged array. From this, we simply go to the k’th index.
C++
#include <iostream>
using namespace std;
int kth( int arr1[], int arr2[], int m, int n, int k)
{
int sorted1[m + n];
int i = 0, j = 0, d = 0;
while (i < m && j < n)
{
if (arr1[i] < arr2[j])
sorted1[d++] = arr1[i++];
else
sorted1[d++] = arr2[j++];
}
while (i < m)
sorted1[d++] = arr1[i++];
while (j < n)
sorted1[d++] = arr2[j++];
return sorted1[k - 1];
}
int main()
{
int arr1[5] = {2, 3, 6, 7, 9};
int arr2[4] = {1, 4, 8, 10};
int k = 5;
cout << kth(arr1, arr2, 5, 4, k);
return 0;
}
|
Java
class Main
{
static int kth( int arr1[], int arr2[], int m, int n, int k)
{
int [] sorted1 = new int [m + n];
int i = 0 , j = 0 , d = 0 ;
while (i < m && j < n)
{
if (arr1[i] < arr2[j])
sorted1[d++] = arr1[i++];
else
sorted1[d++] = arr2[j++];
}
while (i < m)
sorted1[d++] = arr1[i++];
while (j < n)
sorted1[d++] = arr2[j++];
return sorted1[k - 1 ];
}
public static void main (String[] args)
{
int arr1[] = { 2 , 3 , 6 , 7 , 9 };
int arr2[] = { 1 , 4 , 8 , 10 };
int k = 5 ;
System.out.print(kth(arr1, arr2, 5 , 4 , k));
}
}
|
Python3
def kth(arr1, arr2, m, n, k):
sorted1 = [ 0 ] * (m + n)
i = 0
j = 0
d = 0
while (i < m and j < n):
if (arr1[i] < arr2[j]):
sorted1[d] = arr1[i]
i + = 1
else :
sorted1[d] = arr2[j]
j + = 1
d + = 1
while (i < m):
sorted1[d] = arr1[i]
d + = 1
i + = 1
while (j < n):
sorted1[d] = arr2[j]
d + = 1
j + = 1
return sorted1[k - 1 ]
arr1 = [ 2 , 3 , 6 , 7 , 9 ]
arr2 = [ 1 , 4 , 8 , 10 ]
k = 5
print (kth(arr1, arr2, 5 , 4 , k))
|
C#
class GFG {
static int kth( int [] arr1, int [] arr2, int m, int n,
int k)
{
int [] sorted1 = new int [m + n];
int i = 0, j = 0, d = 0;
while (i < m && j < n) {
if (arr1[i] < arr2[j])
sorted1[d++] = arr1[i++];
else
sorted1[d++] = arr2[j++];
}
while (i < m)
sorted1[d++] = arr1[i++];
while (j < n)
sorted1[d++] = arr2[j++];
return sorted1[k - 1];
}
static void Main()
{
int [] arr1 = { 2, 3, 6, 7, 9 };
int [] arr2 = { 1, 4, 8, 10 };
int k = 5;
System.Console.WriteLine(kth(arr1, arr2, 5, 4, k));
}
}
|
PHP
<?php
function kth( $arr1 , $arr2 ,
$m , $n , $k )
{
$sorted1 [ $m + $n ] = 0;
$i = 0;
$j = 0;
$d = 0;
while ( $i < $m && $j < $n )
{
if ( $arr1 [ $i ] < $arr2 [ $j ])
$sorted1 [ $d ++] = $arr1 [ $i ++];
else
$sorted1 [ $d ++] = $arr2 [ $j ++];
}
while ( $i < $m )
$sorted1 [ $d ++] = $arr1 [ $i ++];
while ( $j < $n )
$sorted1 [ $d ++] = $arr2 [ $j ++];
return $sorted1 [ $k - 1];
}
$arr1 = array (2, 3, 6, 7, 9);
$arr2 = array (1, 4, 8, 10);
$k = 5;
echo kth( $arr1 , $arr2 , 5, 4, $k );
?>
|
Javascript
<script>
function kth(arr1 , arr2 , m , n , k) {
var sorted1 = Array(m + n).fill(0);
var i = 0, j = 0, d = 0;
while (i < m && j < n) {
if (arr1[i] < arr2[j])
sorted1[d++] = arr1[i++];
else
sorted1[d++] = arr2[j++];
}
while (i < m)
sorted1[d++] = arr1[i++];
while (j < n)
sorted1[d++] = arr2[j++];
return sorted1[k - 1];
}
var arr1 = [ 2, 3, 6, 7, 9 ];
var arr2 = [ 1, 4, 8, 10 ];
var k = 5;
document.write(kth(arr1, arr2, 5, 4, k));
</script>
|
Time Complexity: O(n)
Auxiliary Space : O(m + n)
Space Optimized Version of above approach: We can avoid the use of extra array.
C++
#include <bits/stdc++.h>
using namespace std;
int find( int A[], int B[], int m,
int n, int k_req)
{
int k = 0, i = 0, j = 0;
while (i < m && j < n)
{
if (A[i] < B[j])
{
k++;
if (k == k_req)
return A[i];
i++;
}
else
{
k++;
if (k == k_req)
return B[j];
j++;
}
}
while (i < m)
{
k++;
if (k == k_req)
return A[i];
i++;
}
while (j < n)
{
k++;
if (k == k_req)
return B[j];
j++;
}
}
int main()
{
int A[5] = { 2, 3, 6, 7, 9 };
int B[4] = { 1, 4, 8, 10 };
int k = 5;
cout << find(A, B, 5, 4, k);
return 0;
}
|
Java
import java.io.*;
class GFG {
public static int find( int A[], int B[], int m, int n,
int k_req)
{
int k = 0 , i = 0 , j = 0 ;
while (i < m && j < n) {
if (A[i] < B[j]) {
k++;
if (k == k_req)
return A[i];
i++;
}
else {
k++;
if (k == k_req)
return B[j];
j++;
}
}
while (i < m) {
k++;
if (k == k_req)
return A[i];
i++;
}
while (j < n) {
k++;
if (k == k_req)
return B[j];
j++;
}
return - 1 ;
}
public static void main(String[] args)
{
int [] A = { 2 , 3 , 6 , 7 , 9 };
int [] B = { 1 , 4 , 8 , 10 };
int k = 5 ;
System.out.println(find(A, B, 5 , 4 , k));
}
}
|
Python3
def find(A, B, m, n, k_req):
i, j, k = 0 , 0 , 0
while i < len (A) and j < len (B):
if A[i] < B[j]:
k + = 1
if k = = k_req:
return A[i]
i + = 1
else :
k + = 1
if k = = k_req:
return B[j]
j + = 1
while i < len (A):
k + = 1
if k = = k_req:
return A[i]
i + = 1
while j < len (B):
k + = 1
if k = = k_req:
return B[j]
j + = 1
A = [ 2 , 3 , 6 , 7 , 9 ]
B = [ 1 , 4 , 8 , 10 ]
k = 5 ;
print (find(A, B, 5 , 4 , k))
|
C#
using System;
public class GFG
{
public static int find( int [] A, int [] B,
int m, int n, int k_req)
{
int k = 0, i = 0, j = 0;
while (i < m && j < n) {
if (A[i] < B[j]) {
k++;
if (k == k_req)
return A[i];
i++;
}
else {
k++;
if (k == k_req)
return B[j];
j++;
}
}
while (i < m)
{
k++;
if (k == k_req)
return A[i];
i++;
}
while (j < n)
{
k++;
if (k == k_req)
return B[j];
j++;
}
return -1;
}
static public void Main (){
int [] A = { 2, 3, 6, 7, 9 };
int [] B = { 1, 4, 8, 10 };
int k = 5;
Console.WriteLine(find(A, B, 5, 4, k));
}
}
|
Javascript
<script>
function find(A, B, m, n, k_req)
{
let k = 0, i = 0, j = 0;
while (i < m && j < n) {
if (A[i] < B[j]) {
k++;
if (k == k_req)
return A[i];
i++;
}
else {
k++;
if (k == k_req)
return B[j];
j++;
}
}
while (i < m) {
k++;
if (k == k_req)
return A[i];
i++;
}
while (j < n) {
k++;
if (k == k_req)
return B[j];
j++;
}
return -1;
}
let A = [ 2, 3, 6, 7, 9 ];
let B = [ 1, 4, 8, 10 ];
let k = 5;
document.write(find(A, B, 5, 4, k));
</script>
|
Time Complexity: O(k)
Auxiliary Space: O(1)
Divide And Conquer Approach 1:
While the previous method works, can we make our algorithm more efficient? The answer is yes. By using a divide and conquer approach, similar to the one used in binary search, we can attempt to find the k’th element in a more efficient way.
- Compare the middle elements of arrays arr1 and arr2, let us call these indices mid1 and mid2 respectively. Let us assume arr1[mid1] > arr2[mid2], then clearly the elements after mid2 cannot be the required element. Set the last element of arr2 to be arr2[mid2].
In this way, define a new subproblem with half the size of one of the arrays.
C++
#include <iostream>
using namespace std;
int kth( int *arr1, int *arr2, int *end1, int *end2, int k)
{
if (arr1 == end1)
return arr2[k];
if (arr2 == end2)
return arr1[k];
int mid1 = (end1 - arr1) / 2;
int mid2 = (end2 - arr2) / 2;
if (mid1 + mid2 < k)
{
if (arr1[mid1] > arr2[mid2])
return kth(arr1, arr2 + mid2 + 1, end1, end2,
k - mid2 - 1);
else
return kth(arr1 + mid1 + 1, arr2, end1, end2,
k - mid1 - 1);
}
else
{
if (arr1[mid1] > arr2[mid2])
return kth(arr1, arr2, arr1 + mid1, end2, k);
else
return kth(arr1, arr2, end1, arr2 + mid2, k);
}
}
int main()
{
int arr1[5] = {2, 3, 6, 7, 9};
int arr2[4] = {1, 4, 8, 10};
int k = 5;
cout << kth(arr1, arr2, arr1 + 5, arr2 + 4, k - 1);
return 0;
}
|
Java
import java.io.*;
import java.util.Arrays;
public class MainClass {
static int kth( int [] arr1, int [] arr2, int n, int m, int k) {
if (n == 1 || m == 1 ) {
if (m == 1 ) {
int [] temp = arr1;
arr1 = arr2;
arr2 = temp;
m = n;
}
if (k == 1 ) {
return Math.min(arr1[ 0 ], arr2[ 0 ]);
} else if (k == m + 1 ) {
return Math.max(arr1[ 0 ], arr2[ 0 ]);
} else {
if (arr2[k - 1 ] < arr1[ 0 ]) {
return arr2[k - 1 ];
} else {
return Math.max(arr1[ 0 ], arr2[k - 2 ]);
}
}
}
int mid1 = (n - 1 ) / 2 ;
int mid2 = (m - 1 ) / 2 ;
if (mid1 + mid2 + 1 < k) {
if (arr1[mid1] < arr2[mid2]) {
return kth(
Arrays.copyOfRange(arr1, mid1 + 1 , n),
arr2,
n - (mid1 + 1 ),
m,
k - (mid1 + 1 )
);
} else {
return kth(
arr1,
Arrays.copyOfRange(arr2, mid2 + 1 , m),
n,
m - (mid2 + 1 ),
k - (mid2 + 1 )
);
}
} else {
if (arr1[mid1] < arr2[mid2]) {
return kth(
arr1,
Arrays.copyOfRange(arr2, 0 , mid2 + 1 ),
n,
mid2 + 1 ,
k
);
} else {
return kth(
Arrays.copyOfRange(arr1, 0 , mid1 + 1 ),
arr2,
mid1 + 1 ,
m,
k
);
}
}
}
public static void main(String[] args) {
int [] arr1 = { 2 , 3 , 6 , 7 , 9 };
int [] arr2 = { 1 , 4 , 8 , 10 };
int k = 5 ;
System.out.println(kth(arr1, arr2, 5 , 4 , k));
}
}
|
Python3
def kth(arr1, arr2, n, m, k):
if n = = 1 or m = = 1 :
if m = = 1 :
arr2, arr1 = arr1, arr2
m = n
if k = = 1 :
return min (arr1[ 0 ], arr2[ 0 ])
elif k = = m + 1 :
return max (arr1[ 0 ], arr2[ 0 ])
else :
if arr2[k - 1 ] < arr1[ 0 ]:
return arr2[k - 1 ]
else :
return max (arr1[ 0 ], arr2[k - 2 ])
mid1 = (n - 1 ) / / 2
mid2 = (m - 1 ) / / 2
if mid1 + mid2 + 1 < k:
if arr1[mid1] < arr2[mid2]:
return kth(arr1[mid1 + 1 :], arr2, n - mid1 - 1 , m, k - mid1 - 1 )
else :
return kth(arr1, arr2[mid2 + 1 :], n, m - mid2 - 1 , k - mid2 - 1 )
else :
if arr1[mid1] < arr2[mid2]:
return kth(arr1, arr2[:mid2 + 1 ], n, mid2 + 1 , k)
else :
return kth(arr1[:mid1 + 1 ], arr2, mid1 + 1 , m, k)
if __name__ = = "__main__" :
arr1 = [ 2 , 3 , 6 , 7 , 9 ]
arr2 = [ 1 , 4 , 8 , 10 ]
k = 5
print (kth(arr1, arr2, 5 , 4 , k))
|
C#
using System;
public class Program {
static int kth( int [] arr1, int [] arr2, int n, int m, int k) {
if (n == 1 || m == 1) {
if (m == 1) {
int [] temp = arr1;
arr1 = arr2;
arr2 = temp;
m = n;
}
if (k == 1) {
return Math.Min(arr1[0], arr2[0]);
} else if (k == m + 1) {
return Math.Max(arr1[0], arr2[0]);
} else {
if (arr2[k - 1] < arr1[0]) {
return arr2[k - 1];
} else {
return Math.Max(arr1[0], arr2[k - 2]);
}
}
}
int mid1 = (n - 1) / 2;
int mid2 = (m - 1) / 2;
if (mid1 + mid2 + 1 < k) {
if (arr1[mid1] < arr2[mid2]) {
return kth(
arr1[(mid1 + 1)..],
arr2,
n - (mid1 + 1),
m,
k - (mid1 + 1)
);
} else {
return kth(
arr1,
arr2[(mid2 + 1)..],
n,
m - (mid2 + 1),
k - (mid2 + 1)
);
}
} else {
if (arr1[mid1] < arr2[mid2]) {
return kth(
arr1,
arr2[..(mid2 + 1)],
n,
mid2 + 1,
k
);
} else {
return kth(
arr1[..(mid1 + 1)],
arr2,
mid1 + 1,
m,
k
);
}
}
}
public static void Main() {
int [] arr1 = { 2, 3, 6, 7, 9 };
int [] arr2 = { 1, 4, 8, 10 };
int k = 5;
Console.WriteLine(kth(arr1, arr2, 5, 4, k));
}
}
|
Javascript
function kth(arr1, start1, end1, arr2, start2, end2, k) {
if (start1 === end1) {
return arr2[start2 + k];
}
if (start2 === end2) {
return arr1[start1 + k];
}
let mid1 = Math.floor((start1 + end1) / 2);
let mid2 = Math.floor((start2 + end2) / 2);
if (mid1 - start1 + mid2 - start2 < k) {
if (arr1[mid1] > arr2[mid2]) {
return kth(arr1, start1, end1, arr2, mid2 + 1, end2, k - (mid2 - start2) - 1);
} else {
return kth(arr1, mid1 + 1, end1, arr2, start2, end2, k - (mid1 - start1) - 1);
}
} else {
if (arr1[mid1] > arr2[mid2]) {
return kth(arr1, start1, mid1, arr2, start2, end2, k);
} else {
return kth(arr1, start1, end1, arr2, start2, mid2, k);
}
}
}
let arr1 = [2, 3, 6, 7, 9];
let arr2 = [1, 4, 8, 10];
let k = 5;
console.log(kth(arr1, 0, arr1.length, arr2, 0, arr2.length, k - 1));
|
Note that in the above code, k is 0 indexed, which means if we want a k that’s 1 indexed, we have to subtract 1 when passing it to the function.
Time Complexity: O(log n + log m)
Auxiliary Space: O(logn + logm)
Divide And Conquer Approach 2:
While the above implementation is very efficient, we can still get away with making it more efficient. Instead of dividing the array into segments of n / 2 and m / 2 and then recursing, we can divide them both by k / 2 and recurse.
The below implementation displays this.
Explanation:
Instead of comparing the middle element of the arrays,
we compare the k / 2nd element.
Let arr1 and arr2 be the arrays.
Now, if arr1[k / 2] arr1[1]
New subproblem:
Array 1 - 6 7 9
Array 2 - 1 4 8 10
k = 5 - 2 = 3
floor(k / 2) = 1
arr1[1] = 6
arr2[1] = 1
arr1[1] > arr2[1]
New subproblem:
Array 1 - 6 7 9
Array 2 - 4 8 10
k = 3 - 1 = 2
floor(k / 2) = 1
arr1[1] = 6
arr2[1] = 4
arr1[1] > arr2[1]
New subproblem:
Array 1 - 6 7 9
Array 2 - 8 10
k = 2 - 1 = 1
Now, we directly compare first elements,
since k = 1.
arr1[1] < arr2[1]
Hence, arr1[1] = 6 is the answer.
C++
#include <iostream>
using namespace std;
int kth( int arr1[], int arr2[], int m, int n, int k,
int st1 = 0, int st2 = 0)
{
if (st1 == m)
return arr2[st2 + k - 1];
if (st2 == n)
return arr1[st1 + k - 1];
if (k == 0 || k > (m - st1) + (n - st2))
return -1;
if (k == 1)
return (arr1[st1] < arr2[st2]) ?
arr1[st1] : arr2[st2];
int curr = k / 2;
if (curr - 1 >= m - st1)
{
if (arr1[m - 1] < arr2[st2 + curr - 1])
return arr2[st2 + (k - (m - st1) - 1)];
else
return kth(arr1, arr2, m, n, k - curr,
st1, st2 + curr);
}
if (curr-1 >= n-st2)
{
if (arr2[n - 1] < arr1[st1 + curr - 1])
return arr1[st1 + (k - (n - st2) - 1)];
else
return kth(arr1, arr2, m, n, k - curr,
st1 + curr, st2);
}
else
{
if (arr1[curr + st1 - 1] < arr2[curr + st2 - 1])
return kth(arr1, arr2, m, n, k - curr,
st1 + curr, st2);
else
return kth(arr1, arr2, m, n, k - curr,
st1, st2 + curr);
}
}
int main()
{
int arr1[5] = {2, 3, 6, 7, 9};
int arr2[4] = {1, 4, 8, 10};
int k = 5;
cout << kth(arr1, arr2, 5, 4, k);
return 0;
}
|
Java
class GFG
{
static int kth( int arr1[], int arr2[], int m,
int n, int k, int st1, int st2)
{
if (st1 == m)
{
return arr2[st2 + k - 1 ];
}
if (st2 == n)
{
return arr1[st1 + k - 1 ];
}
if (k == 0 || k > (m - st1) + (n - st2))
{
return - 1 ;
}
if (k == 1 )
{
return (arr1[st1] < arr2[st2])
? arr1[st1] : arr2[st2];
}
int curr = k / 2 ;
if (curr - 1 >= m - st1)
{
if (arr1[m - 1 ] < arr2[st2 + curr - 1 ])
{
return arr2[st2 + (k - (m - st1) - 1 )];
}
else
{
return kth(arr1, arr2, m, n, k - curr,
st1, st2 + curr);
}
}
if (curr - 1 >= n - st2)
{
if (arr2[n - 1 ] < arr1[st1 + curr - 1 ])
{
return arr1[st1 + (k - (n - st2) - 1 )];
}
else
{
return kth(arr1, arr2, m, n, k - curr,
st1 + curr, st2);
}
}
else
if (arr1[curr + st1 - 1 ] < arr2[curr + st2 - 1 ])
{
return kth(arr1, arr2, m, n, k - curr,
st1 + curr, st2);
}
else
{
return kth(arr1, arr2, m, n, k - curr,
st1, st2 + curr);
}
}
public static void main(String[] args)
{
int arr1[] = { 2 , 3 , 6 , 7 , 9 };
int arr2[] = { 1 , 4 , 8 , 10 };
int k = 5 ;
int st1 = 0 , st2 = 0 ;
System.out.println(kth(arr1, arr2, 5 , 4 , k, st1, st2));
}
}
|
Python3
def kth(arr1, arr2, m, n, k, st1 = 0 , st2 = 0 ):
if (st1 = = m):
return arr2[st2 + k - 1 ]
if (st2 = = n):
return arr1[st1 + k - 1 ]
if (k = = 0 or k > (m - st1) + (n - st2)):
return - 1
if (k = = 1 ):
if (arr1[st1] < arr2[st2]):
return arr1[st1]
else :
return arr2[st2]
curr = int (k / 2 )
if (curr - 1 > = m - st1):
if (arr1[m - 1 ] < arr2[st2 + curr - 1 ]):
return arr2[st2 + (k - (m - st1) - 1 )]
else :
return kth(arr1, arr2, m, n,
k - curr, st1, st2 + curr)
if (curr - 1 > = n - st2):
if (arr2[n - 1 ] < arr1[st1 + curr - 1 ]):
return arr1[st1 + (k - (n - st2) - 1 )]
else :
return kth(arr1, arr2, m, n,
k - curr,st1 + curr, st2)
else :
if (arr1[curr + st1 - 1 ] < arr2[curr + st2 - 1 ]):
return kth(arr1, arr2, m, n, k - curr,
st1 + curr, st2)
else :
return kth(arr1, arr2, m, n, k - curr,
st1, st2 + curr)
arr1 = [ 2 , 3 , 6 , 7 , 9 ]
arr2 = [ 1 , 4 , 8 , 10 ]
k = 5
print (kth(arr1, arr2, 5 , 4 , k))
|
C#
using System;
class GFG
{
static int kth( int []arr1, int []arr2, int m,
int n, int k, int st1, int st2)
{
if (st1 == m)
{
return arr2[st2 + k - 1];
}
if (st2 == n)
{
return arr1[st1 + k - 1];
}
if (k == 0 || k > (m - st1) + (n - st2))
{
return -1;
}
if (k == 1)
{
return (arr1[st1] < arr2[st2])
? arr1[st1] : arr2[st2];
}
int curr = k / 2;
if (curr - 1 >= m - st1)
{
if (arr1[m - 1] < arr2[st2 + curr - 1])
{
return arr2[st2 + (k - (m - st1) - 1)];
}
else
{
return kth(arr1, arr2, m, n, k - curr,
st1, st2 + curr);
}
}
if (curr - 1 >= n - st2)
{
if (arr2[n - 1] < arr1[st1 + curr - 1])
{
return arr1[st1 + (k - (n - st2) - 1)];
}
else
{
return kth(arr1, arr2, m, n, k - curr,
st1 + curr, st2);
}
}
else
if (arr1[curr + st1 - 1] < arr2[curr + st2 - 1])
{
return kth(arr1, arr2, m, n, k - curr,
st1 + curr, st2);
}
else
{
return kth(arr1, arr2, m, n, k - curr,
st1, st2 + curr);
}
}
public static void Main(String[] args)
{
int []arr1 = {2, 3, 6, 7, 9};
int []arr2 = {1, 4, 8, 10};
int k = 5;
int st1 = 0, st2 = 0;
Console.WriteLine(kth(arr1, arr2, 5, 4, k, st1, st2));
}
}
|
Javascript
<script>
function kth(arr1 , arr2 , m , n , k , st1 , st2)
{
if (st1 == m) {
return arr2[st2 + k - 1];
}
if (st2 == n) {
return arr1[st1 + k - 1];
}
if (k == 0 || k > (m - st1) + (n - st2)) {
return -1;
}
if (k == 1) {
return (arr1[st1] < arr2[st2]) ? arr1[st1] : arr2[st2];
}
var curr = parseInt(k / 2);
if (curr - 1 >= m - st1) {
if (arr1[m - 1] < arr2[st2 + curr - 1]) {
return arr2[st2 + (k - (m - st1) - 1)];
} else {
return kth(arr1, arr2, m, n, k - curr, st1, st2 + curr);
}
}
if (curr - 1 >= n - st2) {
if (arr2[n - 1] < arr1[st1 + curr - 1]) {
return arr1[st1 + (k - (n - st2) - 1)];
} else {
return kth(arr1, arr2, m, n, k - curr, st1 + curr, st2);
}
} else
if (arr1[curr + st1 - 1] < arr2[curr + st2 - 1]) {
return kth(arr1, arr2, m, n, k - curr, st1 + curr, st2);
} else {
return kth(arr1, arr2, m, n, k - curr, st1, st2 + curr);
}
}
var arr1 = [ 2, 3, 6, 7, 9 ];
var arr2 = [ 1, 4, 8, 10 ];
var k = 5;
var st1 = 0, st2 = 0;
document.write(kth(arr1, arr2, 5, 4, k, st1, st2));
</script>
|
Time Complexity: O(log k)
Auxiliary Space: O(logk)
Now, k can take a maximum value of m + n. This means that log k can be in the worst case, log(m + n). Logm + logn = log(mn) by properties of logarithms, and when m, n > 2, log(m + n) < log(mn). Thus this algorithm slightly outperforms the previous algorithm. Also, see another simple implemented log k approach suggested by Raj Kumar.
C++
#include <iostream>
using namespace std;
int kth( int arr1[], int m, int arr2[], int n, int k)
{
if (k > (m + n) || k < 1)
return -1;
if (m > n)
return kth(arr2, n, arr1, m, k);
if (m == 0)
return arr2[k - 1];
if (k == 1)
return min(arr1[0], arr2[0]);
int i = min(m, k / 2), j = min(n, k / 2);
if (arr1[i - 1] > arr2[j - 1])
return kth(arr1, m, arr2 + j, n - j, k - j);
else
return kth(arr1 + i, m - i, arr2, n, k - i);
}
int main()
{
int arr1[5] = { 2, 3, 6, 7, 9 };
int arr2[4] = { 1, 4, 8, 10 };
int m = sizeof (arr1) / sizeof (arr1[0]);
int n = sizeof (arr2) / sizeof (arr2[0]);
int k = 5;
int ans = kth(arr1, m, arr2, n, k);
if (ans == -1)
cout << "Invalid query" ;
else
cout << ans;
return 0;
}
|
Java
import java.util.Arrays;
class Gfg {
static int kth( int arr1[], int m, int arr2[], int n,
int k)
{
if (k > (m + n) || k < 1 )
return - 1 ;
if (m > n)
return kth(arr2, n, arr1, m, k);
if (m == 0 )
return arr2[k - 1 ];
if (k == 1 )
return Math.min(arr1[ 0 ], arr2[ 0 ]);
int i = Math.min(m, k / 2 );
int j = Math.min(n, k / 2 );
if (arr1[i - 1 ] > arr2[j - 1 ]) {
int temp[] = Arrays.copyOfRange(arr2, j, n);
return kth(arr1, m, temp, n - j, k - j);
}
int temp[] = Arrays.copyOfRange(arr1, i, m);
return kth(temp, m - i, arr2, n, k - i);
}
public static void main(String[] args)
{
int arr1[] = { 2 , 3 , 6 , 7 , 9 };
int arr2[] = { 1 , 4 , 8 , 10 };
int m = arr1.length;
int n = arr2.length;
int k = 5 ;
int ans = kth(arr1, m, arr2, n, k);
if (ans == - 1 )
System.out.println( "Invalid query" );
else
System.out.println(ans);
}
}
|
Python3
def kth(arr1, m, arr2, n, k):
if (k > (m + n) or k < 1 ):
return - 1
if (m > n):
return kth(arr2, n, arr1, m, k)
if (m = = 0 ):
return arr2[k - 1 ]
if (k = = 1 ):
return min (arr1[ 0 ], arr2[ 0 ])
i = min (m, k / / 2 )
j = min (n, k / / 2 )
if (arr1[i - 1 ] > arr2[j - 1 ]):
return kth(arr1, m, arr2[j:], n - j, k - j)
else :
return kth(arr1[i:], m - i, arr2, n, k - i)
arr1 = [ 2 , 3 , 6 , 7 , 9 ]
arr2 = [ 1 , 4 , 8 , 10 ]
m = len (arr1)
n = len (arr2)
k = 5
ans = kth(arr1, m, arr2, n, k)
if (ans = = - 1 ):
print ( "Invalid query" )
else :
print (ans)
|
C#
using System;
using System.Collections.Generic;
public class GFG{
static int kth( int [] arr1, int m, int [] arr2, int n,
int k)
{
if (k > (m + n) || k < 1)
return -1;
if (m > n)
return kth(arr2, n, arr1, m, k);
if (m == 0)
return arr2[k - 1];
if (k == 1)
return Math.Min(arr1[0], arr2[0]);
int i = Math.Min(m, k / 2);
int j = Math.Min(n, k / 2);
if (arr1[i - 1] > arr2[j - 1]) {
int [] temp = new int [n - j];
Array.Copy(arr2, j, temp, 0, n-j);
return kth(arr1, m, temp, n - j, k - j);
}
int [] temp1 = new int [m-i];
Array.Copy(arr1, i, temp1, 0, m-i);
return kth(temp1, m - i, arr2, n, k - i);
}
public static void Main()
{
int [] arr1 = { 2, 3, 6, 7, 9 };
int [] arr2 = { 1, 4, 8, 10 };
int m = arr1.Length;
int n = arr2.Length;
int k = 5;
int ans = kth(arr1, m, arr2, n, k);
if (ans == -1)
Console.WriteLine( "Invalid query" );
else
Console.WriteLine(ans);
}
}
|
Javascript
<script>
function kth(arr1, m, arr2, n, k)
{
if (k > (m + n) || k < 1){
return -1;
}
if (m > n){
return kth(arr2, n, arr1, m, k);
}
if (m == 0){
return arr2[k - 1];
}
if (k == 1){
return Math.min(arr1[0], arr2[0]);
}
let i = Math.min(m, parseInt(k / 2));
let j = Math.min(n, parseInt(k / 2));
if (arr1[i - 1] > arr2[j - 1]){
let temp = arr2.slice(j,n)
return kth(arr1, m, temp, n - j, k - j);
}
else {
let temp = arr1.slice(i,m)
return kth( temp, m - i, arr2, n, k - i);
}
}
let arr1 = [ 2, 3, 6, 7, 9 ];
let arr2 = [ 1, 4, 8, 10 ];
let m = 5;
let n = 4;
let k = 5;
let ans = kth(arr1, m, arr2, n, k);
if (ans == -1){
document.write( "Invalid query" );
}
else {
document.write(ans);
}
</script>
|
Time Complexity:O(log k)
Auxiliary Space: O(log k)
Another Approach: (Using Min Heap)
- Push the elements of both arrays to a priority queue (min-heap).
- Pop-out k-1 elements from the front.
- Element at the front of the priority queue is the required answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int kth( int * a, int * b, int n, int m, int k)
{
priority_queue< int , vector< int >,
greater< int > > pq;
for ( int i = 0; i < n; i++) {
pq.push(a[i]);
}
for ( int i = 0; i < m; i++) {
pq.push(b[i]);
}
while (k-- > 1) {
pq.pop();
}
return pq.top();
}
int main()
{
int arr1[5] = {2, 3, 6, 7, 9};
int arr2[4] = {1, 4, 8, 10};
int k = 5;
cout << kth(arr1, arr2, 5, 4, k);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int kth( int a[], int b[],
int n, int m, int k)
{
PriorityQueue<Integer> pq =
new PriorityQueue<>();
for ( int i = 0 ; i < n; i++) {
pq.offer(a[i]);
}
for ( int i = 0 ; i < m; i++) {
pq.offer(b[i]);
}
while (k-- > 1 ) {
pq.remove();
}
return pq.peek();
}
public static void main(String[] args)
{
int arr1[] = { 2 , 3 , 6 , 7 , 9 };
int arr2[] = { 1 , 4 , 8 , 10 };
int k = 5 ;
System.out.print(kth(arr1, arr2, 5 , 4 , k));
}
}
|
Python3
def kth(a , b , n , m , k):
pq = [];
for i in range (n):
pq.append(a[i]);
for i in range (m):
pq.append(b[i]);
pq = sorted (pq, reverse = True )
while (k > 1 ):
k - = 1 ;
pq.pop();
return pq.pop();
arr1 = [ 2 , 3 , 6 , 7 , 9 ];
arr2 = [ 1 , 4 , 8 , 10 ];
k = 5 ;
print (kth(arr1, arr2, 5 , 4 , k));
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static int kth( int []a, int []b, int n, int m, int k) {
List< int > pq = new List< int >();
for ( int i = 0; i < n; i++) {
pq.Add(a[i]);
}
for ( int i = 0; i < m; i++) {
pq.Add(b[i]);
}
pq.Sort();
while (k-- > 1) {
pq.RemoveAt(0);
}
return pq[0];
}
public static void Main(String[] args) {
int []arr1 = { 2, 3, 6, 7, 9 };
int []arr2 = { 1, 4, 8, 10 };
int k = 5;
Console.Write(kth(arr1, arr2, 5, 4, k));
}
}
|
Javascript
<script>
function kth(a , b , n , m , k) {
var pq = [];
for (i = 0; i < n; i++) {
pq.push(a[i]);
}
for (i = 0; i < m; i++) {
pq.push(b[i]);
}
pq.sort((a,b)=>b-a);
while (k-- > 1) {
pq.pop();
}
return pq.pop();
}
var arr1 = [ 2, 3, 6, 7, 9 ];
var arr2 = [ 1, 4, 8, 10 ];
var k = 5;
document.write(kth(arr1, arr2, 5, 4, k));
</script>
|
Time Complexity: O(N*logN)
Auxiliary Space: O(m+n)
Another Approach : (Using Upper Bound STL)
Given two sorted arrays of size m and n respectively, you are tasked with finding the element that would be at the k’th position of the final sorted array.
Examples :
Input : Array 1 – 2 3 6 7 9
Array 2 – 1 4 8 10
k = 5
Output : 6
Explanation: The final sorted array would be –
1, 2, 3, 4, 6, 7, 8, 9, 10
The 5th element of this array is 6, The 1st element of this array is 1. The thing to notice here is upper_bound(6) gives 5, upper_bound(4) gives 4 that is number of element equal to or less than the number we are giving as input to upper_bound().
Here is another example
Input : Array 1 – 100 112 256 349 770
Array 2 – 72 86 113 119 265 445 892
k = 7
Output : 256
Explanation: Final sorted array is –
72, 86, 100, 112, 113, 119, 256, 265, 349, 445, 770, 892
7th element of this array is 256.
Observation required :
The simplest method to solve this question is using upper_bound to check what is the position of a element in the sorted array. The upper_bound function return the pointer to element which is greater than the element we searched.
So to find the kth element we need to just find the element whose upper_bound() is 4. So again now we know what upper_bound() gives us we need 1 last observation to solve this question. If we have been given 2 arrays, We just need to the sum of upper_bound for the 2 arrays
Input : Array 1 – 2 3 6 7 9
Array 2 – 1 4 8 10
k = 5
Value of upper_bound for value(6) in array1 is 3 and for array 2 is 2. This give us a total of 5. which is the answer.
Algorithm :
- We take a mid between [L,R] using the formula mid = (L+R)/2.
- Check if the middle can be the kth element using upper_bound() function
- Find the sum of upper_bound() for both the arrays and if the sum is >= K, It’s a possible value of kth element.
- If sum is >= K then we assign R = mid – 1.
- else if sum <k then the current mid is too small and we assign L = mid+1.
- Repeat from top
- Return the smallest value found.
Here is the implementation for the optimized method :
C++
#include <bits/stdc++.h>
using namespace std;
long long int maxN
= 1e10;
long long int kthElement( int arr1[], int arr2[], int n,
int m, int k)
{
long long int left = 1,
right
= maxN;
long long int ans = 1e15;
while (left <= right) {
long long int mid = (left + right) / 2;
long long int up_cnt
= upper_bound(arr1, arr1 + n, mid) - arr1;
up_cnt += upper_bound(arr2, arr2 + m, mid) - arr2;
if (up_cnt >= k) {
ans = min(ans,
mid);
right
= mid - 1;
}
else
left = mid + 1;
}
return ans;
}
int main()
{
int n = 5, m = 7, k = 7;
int arr1[n] = { 100, 112, 256, 349, 770 };
int arr2[m] = { 72, 86, 113, 119, 265, 445, 892 };
cout << kthElement(arr1, arr2, n, m, k) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG{
static long maxN = ( long )1e10;
static int upperBound( int [] a, int low,
int high, long element)
{
while (low < high){
int middle = low + (high - low)/ 2 ;
if (a[middle] > element)
high = middle;
else
low = middle + 1 ;
}
return low;
}
static long kthElement( int arr1[], int arr2[], int n,
int m, int k)
{
long left = 1 , right = maxN;
long ans = ( long )1e15;
while (left <= right) {
long mid = (left + right) / 2 ;
long up_cnt = upperBound(arr1, 0 , n, mid);
up_cnt += upperBound(arr2, 0 , m, mid);
if (up_cnt >= k) {
ans = Math.min(ans,
mid);
right
= mid - 1 ;
}
else
left = mid + 1 ;
}
return ans;
}
public static void main(String[] args)
{
int n = 5 , m = 7 , k = 7 ;
int arr1[] = { 100 , 112 , 256 , 349 , 770 };
int arr2[] = { 72 , 86 , 113 , 119 , 265 , 445 , 892 };
System.out.print(kthElement(arr1, arr2, n, m, k) + "\n" );
}
}
|
Python3
maxN = 10 * * 10
def upperBound(a, low, high, element):
while (low < high):
middle = low + (high - low) / / 2
if (a[middle] > element):
high = middle
else :
low = middle + 1
return low
def kthElement(arr1, arr2, n, m, k):
left = 1
right = maxN
ans = 10 * * 15
while (left < = right):
mid = (left + right) / / 2
up_cnt = upperBound(arr1, 0 , n, mid)
up_cnt + = upperBound(arr2, 0 , m, mid)
if (up_cnt > = k):
ans = min (ans, mid)
right = mid - 1
else :
left = mid + 1
return ans
n = 5
m = 7
k = 7
arr1 = [ 100 , 112 , 256 , 349 , 770 ]
arr2 = [ 72 , 86 , 113 , 119 , 265 , 445 , 892 ]
print (kthElement(arr1, arr2, n, m, k))
|
C#
using System;
public class GFG{
static long maxN = ( long )1e10;
static int upperBound( int [] a, int low,
int high, long element)
{
while (low < high){
int middle = low + (high - low)/2;
if (a[middle] > element)
high = middle;
else
low = middle + 1;
}
return low;
}
static long kthElement( int [] arr1, int [] arr2, int n,
int m, int k)
{
long left = 1, right = maxN;
long ans = ( long )1e15;
while (left <= right) {
long mid = (left + right) / 2;
long up_cnt = upperBound(arr1,0, n, mid);
up_cnt += upperBound(arr2, 0, m, mid);
if (up_cnt >= k) {
ans = Math.Min(ans,
mid);
right
= mid - 1;
}
else
left = mid + 1;
}
return ans;
}
static public void Main (){
int n = 5, m = 7, k = 7;
int [] arr1 = { 100, 112, 256, 349, 770 };
int [] arr2 = { 72, 86, 113, 119, 265, 445, 892 };
Console.Write(kthElement(arr1, arr2, n, m, k) + "\n" );
}
}
|
Javascript
<script>
var maxN = 10000000000;
function upperBound(a, low, high, element)
{
while (low < high){
var middle = parseInt(low + (high - low)/2);
if (a[middle] > element)
high = middle;
else
low = middle + 1;
}
return low;
}
function kthElement(arr1, arr2, n, m, k)
{
var left = 1
var right = maxN;
var ans = 1000000000000000;
while (left <= right) {
var mid = parseInt((left + right) / 2);
var up_cnt = upperBound(arr1,0, n, mid);
up_cnt += upperBound(arr2, 0, m, mid);
if (up_cnt >= k) {
ans = Math.min(ans,
mid);
right
= mid - 1;
}
else
left = mid + 1;
}
return ans;
}
var n = 5, m = 7, k = 7;
var arr1 = [ 100, 112, 256, 349, 770 ];
var arr2 = [ 72, 86, 113, 119, 265, 445, 892 ];
document.write(kthElement(arr1, arr2, n, m, k));
</script>
|
Time Complexity : O( Log( maxN ).log( N+M ) )
Auxiliary Space : O( 1 )
This article is contributed by Aditya Kamath. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.