Merge K sorted arrays of different sizes | ( Divide and Conquer Approach )
Last Updated :
17 Feb, 2023
Given k sorted arrays of different length, merge them into a single array such that the merged array is also sorted.
Examples:
Input : {{3, 13},
{8, 10, 11}
{9, 15}}
Output : {3, 8, 9, 10, 11, 13, 15}
Input : {{1, 5},
{2, 3, 4}}
Output : {1, 2, 3, 4, 5}
Let S be the total number of elements in all the arrays.
Simple Approach: A simple approach is to append the arrays one after another and sort them. Time complexity in this case will be O( S * log(S)).
Efficient Approach: An efficient solution will be to take pairs of arrays at each step. Then merge the pairs using the two pointer technique of merging two sorted arrays. Thus, after merging all the pairs, the number of arrays will reduce by half.
We, will continue this till the number of remaining arrays doesn’t become 1. Thus, the number of steps required will be of the order log(k) and since at each step, we are taking O(S) time to perform the merge operations, the total time complexity of this approach becomes O(S * log(k)).
We already have discussed this approach for merging K sorted arrays of same sizes.
Since in this problem the arrays are of different sizes, we will use dynamic arrays ( eg: vector in case of C++ or arraylist in case of Java ) because they reduce the number of lines and work load significantly.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <vector>
using namespace std;
vector< int > mergeTwoArrays(vector< int > l, vector< int > r)
{
vector< int > ret;
int l_in = 0, r_in = 0;
while (l_in + r_in < l.size() + r.size()) {
if (l_in != l.size() && (r_in == r.size() || l[l_in] < r[r_in])) {
ret.push_back(l[l_in]);
l_in++;
}
else {
ret.push_back(r[r_in]);
r_in++;
}
}
return ret;
}
vector< int > mergeArrays(vector<vector< int > > arr)
{
vector<vector< int > > arr_s;
while (arr.size() != 1) {
arr_s.clear();
for ( int i = 0; i < arr.size(); i += 2) {
if (i == arr.size() - 1)
arr_s.push_back(arr[i]);
else
arr_s.push_back(mergeTwoArrays(arr[i],
arr[i + 1]));
}
arr = arr_s;
}
return arr[0];
}
int main()
{
vector<vector< int > > arr{ { 3, 13 },
{ 8, 10, 11 },
{ 9, 15 } };
vector< int > output = mergeArrays(arr);
for ( int i = 0; i < output.size(); i++)
cout << output[i] << " " ;
return 0;
}
|
Java
import java.io.*;
import java.util.ArrayList;
import java.util.List;
class GFG {
public static List<Integer> mergeTwoArrays(List<Integer> l, List<Integer> r) {
List<Integer> ret = new ArrayList<>();
int lIn = 0 , rIn = 0 ;
while (lIn + rIn < l.size() + r.size()) {
if (lIn != l.size() && (rIn == r.size() || l.get(lIn) < r.get(rIn))) {
ret.add(l.get(lIn));
lIn += 1 ;
} else {
ret.add(r.get(rIn));
rIn += 1 ;
}
}
return ret;
}
public static List<Integer> mergeArrays(List<List<Integer>> arr) {
while (arr.size() != 1 ) {
List<List<Integer>> arrS = new ArrayList<>();
for ( int i = 0 ; i < arr.size(); i += 2 ) {
if (i == arr.size() - 1 ) {
arrS.add(arr.get(i));
} else {
arrS.add(mergeTwoArrays(arr.get(i), arr.get(i + 1 )));
}
}
arr = arrS;
}
return arr.get( 0 );
}
public static void main(String[] args) {
List<List<Integer>> arr = new ArrayList<>();
arr.add(List.of( 3 , 13 ));
arr.add(List.of( 8 , 10 , 11 ));
arr.add(List.of( 9 , 15 ));
List<Integer> output = mergeArrays(arr);
for ( int i = 0 ; i < output.size(); i++) {
System.out.print(output.get(i) + " " );
}
}
}
|
Python3
def mergeTwoArrays(l, r):
ret = []
l_in, r_in = 0 , 0
while l_in + r_in < len (l) + len (r):
if (l_in ! = len (l) and
(r_in = = len (r) or
l[l_in] < r[r_in])):
ret.append(l[l_in])
l_in + = 1
else :
ret.append(r[r_in])
r_in + = 1
return ret
def mergeArrays(arr):
arr_s = []
while len (arr) ! = 1 :
arr_s[:] = []
for i in range ( 0 , len (arr), 2 ):
if i = = len (arr) - 1 :
arr_s.append(arr[i])
else :
arr_s.append(mergeTwoArrays(arr[i],
arr[i + 1 ]))
arr = arr_s[:]
return arr[ 0 ]
if __name__ = = "__main__" :
arr = [[ 3 , 13 ],
[ 8 , 10 , 11 ],
[ 9 , 15 ]]
output = mergeArrays(arr)
for i in range ( 0 , len (output)):
print (output[i], end = " " )
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static List< int > mergeTwoArrays(List< int > l, List< int > r) {
List< int > ret = new List< int >();
int l_in = 0, r_in = 0;
while (l_in + r_in < l.Count + r.Count) {
if (l_in != l.Count &&
(r_in == r.Count || l[l_in] < r[r_in])) {
ret.Add(l[l_in]);
l_in += 1;
} else {
ret.Add(r[r_in]);
r_in += 1;
}
}
return ret;
}
static List< int > mergeArrays(List<List< int >> arr) {
List<List< int >> arr_s = new List<List< int >>();
while (arr.Count != 1) {
arr_s.Clear();
for ( int i = 0; i < arr.Count; i += 2) {
if (i == arr.Count - 1) {
arr_s.Add(arr[i]);
} else {
arr_s.Add(mergeTwoArrays(arr[i], arr[i + 1]));
}
}
arr = arr_s.GetRange(0, arr_s.Count);
}
return arr[0];
}
public static void Main() {
List<List< int >> arr = new List<List< int >> {
new List< int > {3, 13},
new List< int > {8, 10, 11},
new List< int > {9, 15}
};
List< int > output = mergeArrays(arr);
for ( int i = 0; i < output.Count; i++) {
Console.Write(output[i] + " " );
}
}
}
|
Javascript
<script>
function mergeTwoArrays(l, r)
{
var ret = [];
var l_in = 0, r_in = 0;
while (l_in + r_in < l.length + r.length) {
if (l_in != l.length && (r_in == r.length || l[l_in] < r[r_in])) {
ret.push(l[l_in]);
l_in++;
}
else {
ret.push(r[r_in]);
r_in++;
}
}
return ret;
}
function mergeArrays(arr)
{
var arr_s = [];
while (arr.length != 1) {
arr_s = [];
for ( var i = 0; i < arr.length; i += 2) {
if (i == arr.length - 1)
arr_s.push(arr[i]);
else
arr_s.push(mergeTwoArrays(arr[i],
arr[i + 1]));
}
arr = arr_s;
}
return arr[0];
}
var arr = [ [ 3, 13 ],
[ 8, 10, 11 ],
[ 9, 15 ] ];
var output = mergeArrays(arr);
for ( var i = 0; i < output.length; i++)
document.write(output[i] + " " );
</script>
|
Time Complexity: O(S*logK)
Auxiliary Space: O(logK)
Note that there exist a better solution using heap (or priority queue). The time complexity of the heap based solution is O(N Log k) where N is the total number of elements in all K arrays.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...