Merge K sorted arrays | Set 3 ( Using Divide and Conquer Approach )

01 Nov, 2021
Giving k sorted arrays, each of size N, the task is to merge them into a single sorted array.
Examples: 
Input: arr[][] = {{5, 7, 15, 18},
                   {1, 8, 9, 17},
                   {1, 4, 7, 7}}
Output: {1, 1, 4, 5, 7, 7, 7, 8, 9, 15, 17, 18}

Input: arr[][] = {{3, 2, 1}
                   {6, 5, 4}}
Output:  {1, 2, 3, 4, 5, 6}
Prerequisite: Merge SortSimple Approach: A simple solution is to append all the arrays one after another and sort them.  
C++14
Java
Python3
C#
Javascript
// C++ program to merge K// sorted arrays#include <bits/stdc++.h>using namespace std;#define N 4 // Merge and sort k arraysvoid merge_and_sort(    vector<int> &output, vector<vector<int>> arr,    int n, int k){    // Put the elements in sorted array.    for (int i = 0; i < k; i++) {        for (int j = 0; j < n; j++) {            output[(i * n) + j] = arr[i][j];        }    }     // Sort the output array    sort(output.begin(), output.end());} // Driver Functionint main(){    // Input 2D-array    vector<vector<int>> arr = { { 5, 7, 15, 18 },                     { 1, 8, 9, 17 },                     { 1, 4, 7, 7 } };    int n = N;         // Number of arrays    int k = arr.size();     // Output array    vector<int> output(n*k);     merge_and_sort(output, arr, n, k);     // Print merged array    for (int i = 0; i < n * k; i++)        cout << output[i] << " ";     return 0;}
// Java program to merge K// sorted arraysimport java.util.*;class GFG{    static int N = 4;          // Merge and sort k arrays    static void merge_and_sort(int output[], int arr[][],                               int n, int k)    {        // Put the elements in sorted array.        for (int i = 0; i < k; i++)        {            for (int j = 0; j < n; j++)            {                output[i * n + j] = arr[i][j];            }        }               // Sort the output array        Arrays.sort(output);    }   // Driver code    public static void main(String[] args)    {               // Input 2D-array        int arr[][] = { { 5, 7, 15, 18 },                         { 1, 8, 9, 17 },                         { 1, 4, 7, 7 } };        int n = N;               // Number of arrays        int k = arr.length;               // Output array        int output[] = new int[n * k];             merge_and_sort(output, arr, n, k);               // Print merged array        for (int i = 0; i < n * k; i++)            System.out.print(output[i] + " ");    }} // This code is contributed by divyesh072019
# Python3 program to merge K# sorted arraysN = 4 # Merge and sort k arraysdef merge_and_sort(output, arr, n, k):     # Put the elements in sorted array.    for  i in range(k):        for j in range(n):            output[i * n + j] = arr[i][j];     # Sort the output array    output.sort() # Driver Functionif __name__=='__main__':     # Input 2D-array    arr = [ [ 5, 7, 15, 18 ],                     [ 1, 8, 9, 17 ],                     [ 1, 4, 7, 7 ] ];    n = N;     # Number of arrays    k = len(arr)     # Output array    output = [0 for i in range(n * k)]    merge_and_sort(output, arr, n, k);     # Print merged array    for  i in range(n * k):        print(output[i], end = ' ')     # This code is contributed by rutvik_56.
// C# program to merge K// sorted arraysusing System;class GFG{         static int N = 4;          // Merge and sort k arrays    static void merge_and_sort(int[] output, int[,] arr,                               int n, int k)    {        // Put the elements in sorted array.        for (int i = 0; i < k; i++)        {            for (int j = 0; j < n; j++)            {                output[i * n + j] = arr[i,j];            }        }               // Sort the output array        Array.Sort(output);    }     // Driver code  static void Main()  {         // Input 2D-array    int[,] arr = { { 5, 7, 15, 18 },                     { 1, 8, 9, 17 },                     { 1, 4, 7, 7 } };    int n = N;       // Number of arrays    int k = arr.GetLength(0);       // Output array    int[] output = new int[n * k];         merge_and_sort(output, arr, n, k);       // Print merged array    for (int i = 0; i < n * k; i++)        Console.Write(output[i] + " ");  }} // This code is contributed by divyeshrabadiya07
<script>    // Javascript program to merge K    // sorted arrays         let N = 4;          // Merge and sort k arrays    function merge_and_sort(output, arr, n, k)    {        // Put the elements in sorted array.        for (let i = 0; i < k; i++)        {            for (let j = 0; j < n; j++)            {                output[i * n + j] = arr[i][j];            }        }                // Sort the output array        output.sort(function(a, b){return a - b});    }         // Input 2D-array    let arr = [ [ 5, 7, 15, 18 ],                 [ 1, 8, 9, 17 ],                 [ 1, 4, 7, 7 ] ];    let n = N;        // Number of arrays    let k = 3;        // Output array    let output = new Array(n * k);        merge_and_sort(output, arr, n, k);        // Print merged array    for (let i = 0; i < n * k; i++)        document.write(output[i] + " ");                 // This code is contributed by mukesh07.</script>
1 1 4 5 7 7 7 8 9 15 17 18
 
Complexity Analysis: 
Time Complexity: O(N*k*log(N*k)). The size of all elements is n*k so the time complexity is O(N*k * log(N*k))
Space Complexity: O(N*k). To store the output array O(N*k) space is required.
Efficient Solution: Approach: The idea becomes clear once we start looking at the k arrays as the intermediate state of the merge sort algorithm. Since there are k arrays that are already sorted, merge the k arrays. Create a recursive function which will take k arrays and divide them into two parts and call the function recursively with each half. The base cases are when the value of k is less than 3. See this article to merge two arrays in O(n) time.
Algorithm:  
Initialize the output array with the size N*k.Call the function divide. Let and represent the range of arrays that are to be merged and thus vary between 0 to k-1.At each step, we call the left and right half of the range recursively so that, they will be sorted and stored in the output array.After that, we merge the left and right half. For merging, we need to determine the range of indexes for the left and right halves in the output array. We can easily find that. Left part will start from the index l * n of the output array.Similarly, right part will start from the index ((l + r) / 2 + 1) * n of the output array.
Initialize the output array with the size N*k.
Call the function divide. Let and represent the range of arrays that are to be merged and thus vary between 0 to k-1.
At each step, we call the left and right half of the range recursively so that, they will be sorted and stored in the output array.
After that, we merge the left and right half. For merging, we need to determine the range of indexes for the left and right halves in the output array. We can easily find that. Left part will start from the index l * n of the output array.Similarly, right part will start from the index ((l + r) / 2 + 1) * n of the output array.
Left part will start from the index l * n of the output array.Similarly, right part will start from the index ((l + r) / 2 + 1) * n of the output array.
Left part will start from the index l * n of the output array.
Similarly, right part will start from the index ((l + r) / 2 + 1) * n of the output array.
C++
Java
Python3
C#
PHP
Javascript
// C++ program to merge K// sorted arrays #include<bits/stdc++.h>#define n 4 using namespace std; // Function to perform merge operationvoid merge(int l, int r, vector<int>& output){    // to store the starting point    // of left and right array    int l_in = l * n, r_in                      = ((l + r) / 2 + 1) * n;     // To store the size of left and    // right array    int l_c = ((l + r) / 2 - l + 1) * n;    int r_c = (r - (l + r) / 2) * n;     // array to temporarily store left    // and right array    int l_arr[l_c], r_arr[r_c];     // storing data in left array    for (int i = 0; i < l_c; i++)        l_arr[i] = output[l_in + i];     // storing data in right array    for (int i = 0; i < r_c; i++)        r_arr[i] = output[r_in + i];     // to store the current index of    // temporary left and right array    int l_curr = 0, r_curr = 0;     // to store the current index    // for output array    int in = l_in;     // two pointer merge for    // two sorted arrays    while (        l_curr + r_curr < l_c + r_c) {        if (            r_curr == r_c            || (l_curr != l_c                && l_arr[l_curr] < r_arr[r_curr]))            output[in]                = l_arr[l_curr],                l_curr++, in++;        else            output[in]                = r_arr[r_curr],                r_curr++, in++;    }} // Code to drive merge-sort and// create recursion treevoid divide(int l, int r, vector<int>& output,            vector<vector<int>> arr){    if (l == r) {         /* base step to initialize the output           array before performing merge           operation */        for (int i = 0; i < n; i++)            output[l * n + i] = arr[l][i];         return;    }     // To sort left half    divide(l, (l + r) / 2,           output, arr);     // To sort right half    divide((l + r) / 2 + 1, r,           output, arr);     // Merge the left and right half    merge(l, r, output);} // Driver Functionint main(){    // input 2D-array    vector<vector<int>> arr = { { 5, 7, 15, 18 },                     { 1, 8, 9, 17 },                     { 1, 4, 7, 7 } };     // Number of arrays    int k = arr.size();     // Output array    vector<int> output(n*k);     divide(0, k - 1, output, arr);     // Print merged array    for (int i = 0; i < n * k; i++)        cout << output[i] << " ";     return 0;}
// Java program to merge// K sorted arraysimport java.util.*; class GFG {     static int n = 4;     // Function to perform    // merge operation    static void merge(        int l, int r, int[] output)    {        // To store the starting point        // of left and right array        int l_in = l * n, r_in                          = ((l + r) / 2 + 1) * n;         // to store the size of left and        // right array        int l_c = ((l + r) / 2 - l + 1) * n;        int r_c = (r - (l + r) / 2) * n;         // array to temporarily store left        // and right array        int l_arr[] = new int[l_c],            r_arr[] = new int[r_c];         // storing data in left array        for (int i = 0; i < l_c; i++)            l_arr[i] = output[l_in + i];         // storing data in right array        for (int i = 0; i < r_c; i++)            r_arr[i] = output[r_in + i];         // to store the current index of        // temporary left and right array        int l_curr = 0, r_curr = 0;         // to store the current index        // for output array        int in = l_in;         // two pointer merge for two sorted arrays        while (l_curr + r_curr < l_c + r_c) {            if (                r_curr == r_c                || (l_curr != l_c                    && l_arr[l_curr] < r_arr[r_curr])) {                output[in] = l_arr[l_curr];                l_curr++;                in++;            }            else {                output[in] = r_arr[r_curr];                r_curr++;                in++;            }        }    }     // Code to drive merge-sort and    // create recursion tree    static void divide(int l, int r, int[] output,                       int arr[][])    {        if (l == r) {             /* base step to initialize the output        array before performing merge        operation */            for (int i = 0; i < n; i++)                output[l * n + i] = arr[l][i];             return;        }         // to sort left half        divide(l, (l + r) / 2, output, arr);         // to sort right half        divide((l + r) / 2 + 1, r, output, arr);         // merge the left and right half        merge(l, r, output);    }     // Driver Code    public static void main(String[] args)    {        // input 2D-array        int arr[][] = { { 5, 7, 15, 18 },                        { 1, 8, 9, 17 },                        { 1, 4, 7, 7 } };         // Number of arrays        int k = arr.length;         // Output array        int[] output = new int[n * k];         divide(0, k - 1, output, arr);         // Print merged array        for (int i = 0; i < n * k; i++)            System.out.print(output[i] + " ");    }} /* This code contributed by PrinciRaj1992 */
# Python3 program to merge K sorted arraysn = 4 ; # Function to perform merge operationdef merge(l, r, output) :         # to store the starting point of    # left and right array    l_in = l * n ;    r_in = ((l + r) // 2 + 1) * n;     # to store the size of left and    # right array    l_c = ((l + r) // 2 - l + 1) * n;    r_c = (r - (l + r) // 2) * n;     # array to temporarily store left    # and right array    l_arr = [0] * l_c; r_arr = [0] * r_c;     # storing data in left array    for i in range(l_c) :        l_arr[i] = output[l_in + i];     # storing data in right array    for i in range(r_c) :        r_arr[i] = output[r_in + i];     # to store the current index of    # temporary left and right array    l_curr = 0 ; r_curr = 0;     # to store the current index    # for output array    in1 = l_in;     # two pointer merge for two sorted arrays    while (l_curr + r_curr < l_c + r_c) :        if (r_curr == r_c or (l_curr != l_c and            l_arr[l_curr] < r_arr[r_curr])) :            output[in1] = l_arr[l_curr];            l_curr += 1; in1 += 1;        else :            output[in1] = r_arr[r_curr];            r_curr += 1; in1 += 1; # Code to drive merge-sort and# create recursion treedef divide(l, r, output, arr) :         if (l == r) :         # base step to initialize the output        # array before performing merge        # operation        for i in range(n) :            output[l * n + i] = arr[l][i];         return;         # to sort left half    divide(l, (l + r) // 2, output, arr);     # to sort right half    divide((l + r) // 2 + 1, r, output, arr);     # merge the left and right half    merge(l, r, output); # Driver codeif __name__ == "__main__" :     # input 2D-array    arr = [[ 5, 7, 15, 18 ],           [ 1, 8, 9, 17 ],           [ 1, 4, 7, 7 ]];         # Number of arrays    k = len(arr);         # Output array    output = [0] * (n * k);         divide(0, k - 1, output, arr);         # Print merged array    for i in range(n * k) :        print(output[i], end = " "); # This code is contributed by Ryuga
// C# program to merge K sorted arraysusing System; class GFG {     static int n = 4;     // Function to perform merge operation    static void merge(int l, int r, int[] output)    {        // to store the starting point of left        // and right array        int l_in = l * n, r_in = ((l + r) / 2 + 1) * n;         // to store the size of left and        // right array        int l_c = ((l + r) / 2 - l + 1) * n;        int r_c = (r - (l + r) / 2) * n;         // array to temporarily store left        // and right array        int[] l_arr = new int[l_c];        int[] r_arr = new int[r_c];         // storing data in left array        for (int i = 0; i < l_c; i++)            l_arr[i] = output[l_in + i];         // storing data in right array        for (int i = 0; i < r_c; i++)            r_arr[i] = output[r_in + i];         // to store the current index of        // temporary left and right array        int l_curr = 0, r_curr = 0;         // to store the current index        // for output array        int index = l_in;         // two pointer merge for two sorted arrays        while (l_curr + r_curr < l_c + r_c) {            if (r_curr == r_c || (l_curr != l_c && l_arr[l_curr] < r_arr[r_curr])) {                output[index] = l_arr[l_curr];                l_curr++;                index++;            }            else {                output[index] = r_arr[r_curr];                r_curr++;                index++;            }        }    }     // Code to drive merge-sort and    // create recursion tree    static void divide(int l, int r, int[] output,                       int[, ] arr)    {        if (l == r) {             /* base step to initialize the output        array before performing merge        operation */            for (int i = 0; i < n; i++)                output[l * n + i] = arr[l, i];             return;        }         // to sort left half        divide(l, (l + r) / 2, output, arr);         // to sort right half        divide((l + r) / 2 + 1, r, output, arr);         // merge the left and right half        merge(l, r, output);    }     // Driver Code    public static void Main(String[] args)    {        // input 2D-array        int[, ] arr = { { 5, 7, 15, 18 },                        { 1, 8, 9, 17 },                        { 1, 4, 7, 7 } };         // Number of arrays        int k = arr.GetLength(0);         // Output array        int[] output = new int[n * k];         divide(0, k - 1, output, arr);         // Print merged array        for (int i = 0; i < n * k; i++)            Console.Write(output[i] + " ");    }} // This code has been contributed by 29AjayKumar
<?php// PHP program to merge K sorted arrays$n = 4; // Function to perform merge operationfunction merge($l, $r, &$output){    global $n;         // to store the starting point of left    // and right array    $l_in = $l * $n;    $r_in = ((int)(($l + $r) / 2) + 1) * $n;     // to store the size of left and    // right array    $l_c = (int)(((($l + $r) / 2) - $l + 1) * $n);    $r_c = ($r - (int)(($l + $r) / 2)) * $n;     // array to temporarily store left    // and right array    $l_arr = array_fill(0, $l_c, 0);    $r_arr = array_fill(0, $r_c, 0);     // storing data in left array    for ($i = 0; $i < $l_c; $i++)        $l_arr[$i] = $output[$l_in + $i];     // storing data in right array    for ($i = 0; $i < $r_c; $i++)        $r_arr[$i] = $output[$r_in + $i];     // to store the current index of    // temporary left and right array    $l_curr = 0;    $r_curr = 0;     // to store the current index    // for output array    $in = $l_in;     // two pointer merge for two sorted arrays    while ($l_curr + $r_curr < $l_c + $r_c)    {        if ($r_curr == $r_c || ($l_curr != $l_c &&            $l_arr[$l_curr] < $r_arr[$r_curr]))        {            $output[$in] = $l_arr[$l_curr];            $l_curr++; $in++;        }        else        {            $output[$in] = $r_arr[$r_curr];            $r_curr++; $in++;        }    }} // Code to drive merge-sort and// create recursion treefunction divide($l, $r, &$output, $arr){    global $n;    if ($l == $r)    {         /* base step to initialize the output        array before performing merge        operation */        for ($i = 0; $i < $n; $i++)            $output[$l * $n + $i] = $arr[$l][$i];         return;    }     // to sort left half    divide($l, (int)(($l + $r) / 2), $output, $arr);     // to sort right half    divide((int)(($l + $r) / 2) + 1, $r, $output, $arr);     // merge the left and right half    merge($l, $r, $output);} // Driver Code // input 2D-array$arr = array(array( 5, 7, 15, 18 ),             array( 1, 8, 9, 17 ),             array( 1, 4, 7, 7 )); // Number of arrays$k = count($arr); // Output array$output = array_fill(0, $n * $k, 0); divide(0, $k - 1, $output, $arr); // Print merged arrayfor ($i = 0; $i < $n * $k; $i++)        print($output[$i] . " ");         // This code is contributed by mits?>
<script> // Javascript program to merge K// sorted arraysvar n = 4; // Function to perform merge operationfunction merge(l, r, output){         // To store the starting point    // of left and right array    var l_in = l * n,        r_in = (parseInt((l + r) / 2) + 1) * n;     // To store the size of left and    // right array    var l_c = (parseInt((l + r) / 2) - l + 1) * n;    var r_c = (r - parseInt((l + r) / 2)) * n;     // array to temporarily store left    // and right array    var l_arr = Array(l_c), r_arr = Array(r_c);     // storing data par left array    for(var i = 0; i < l_c; i++)        l_arr[i] = output[l_in + i];     // storing data par right array    for(var i = 0; i < r_c; i++)        r_arr[i] = output[r_in + i];     // to store the current index of    // temporary left and right array    var l_curr = 0, r_curr = 0;     // to store the current index    // for output array    var par = l_in;     // two pointer merge for    // two sorted arrays    while (l_curr + r_curr < l_c + r_c)    {        if (r_curr == r_c ||           (l_curr != l_c &&           l_arr[l_curr] < r_arr[r_curr]))        {            output[par] = l_arr[l_curr];            l_curr++, par++;        }        else        {            output[par] = r_arr[r_curr];                r_curr++, par++;        }    }} // Code to drive merge-sort and// create recursion treefunction divide(l, r, output, arr){    if (l == r)    {                 /* base step to initialize the output           array before performing merge           operation */        for(var i = 0; i < n; i++)            output[l * n + i] = arr[l][i];         return;    }     // To sort left half    divide(l, parseInt((l + r) / 2),           output, arr);     // To sort right half    divide(parseInt((l + r) / 2) + 1, r,           output, arr);     // Merge the left and right half    merge(l, r, output);} // Driver code // Input 2D-arrayvar arr = [ [ 5, 7, 15, 18 ],            [ 1, 8, 9, 17 ],            [ 1, 4, 7, 7 ] ];             // Number of arraysvar k = arr.length; // Output arrayvar output = Array(n * k);divide(0, k - 1, output, arr); // Print merged arrayfor(var i = 0; i < n * k; i++)    document.write(output[i] + " ");     // This code is contributed by rrrtnx </script>
1 1 4 5 7 7 7 8 9 15 17 18
 
Complexity Analysis: 
Time Complexity: O(N*k*log(k)). In each level the array of size N*k is traversed once, and the number of levels are log(k).
Space Complexity: O(N*k). To store the output array O(N*k) space is required.
We can also solve this problem by using min-heap. 
DivyanshuShekhar1
ankthon
princiraj1992
29AjayKumar
Mithun Kumar
andrew1234
divyesh072019
divyeshrabadiya07
rutvik_56
mukesh07
rrrtnx
surindertarika1234
ashutoshsinghgeeksforgeeks
Merge Sort
Algorithms
Arrays
Divide and Conquer
Sorting
Arrays
Divide and Conquer
Sorting
Merge Sort
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
What is Hashing | A Complete Tutorial
Find if there is a path between two vertices in an undirected graph
How to Start Learning DSA?
Complete Roadmap To Learn DSA From Scratch
Types of Complexity Classes | P, NP, CoNP, NP hard and NP complete
Arrays in Java
Write a program to reverse an array or string
Maximum and minimum of an array using minimum number of comparisons
Largest Sum Contiguous Subarray
Arrays in C/C++