📜  合并k个排序的数组|套装1

📅  最后修改于: 2021-04-27 22:28:50             🧑  作者: Mango

给定k个大小为n的排序数组,将它们合并并打印排序后的输出。
例子:

天真的方法非常天真的方法是创建大小为n * k的输出数组,然后将所有元素复制到输出数组中,然后进行排序。

  • 算法:
    1. 创建大小为n * k的输出数组。
    2. 从头到尾遍历矩阵并将所有元素插入输出数组。
    3. 排序并打印输出数组。
  • 执行:
CPP14
// C++ program to merge k sorted arrays of size n each.
#include
using namespace std;
#define n 4
 
 
// A utility function to print array elements
void printArray(int arr[], int size)
{
   for (int i=0; i < size; i++)
       cout << arr[i] << " ";
}
 
// This function takes an array of arrays as an argument and
// All arrays are assumed to be sorted. It merges them together
// and prints the final sorted output.
void mergeKArrays(int arr[][n], int a, int output[])
{
    int c=0;
     
    //traverse the matrix
    for(int i=0; i


Java
// Java program to merge k sorted arrays of size n each.
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // This function takes an array of arrays as an argument
    // and
    // All arrays are assumed to be sorted. It merges them
    // together and prints the final sorted output.
    public static void mergeKArrays(int[][] arr, int a,
                                    int[] output)
    {
        int c = 0;
 
        // traverse the matrix
        for (int i = 0; i < a; i++) {
            for (int j = 0; j < 4; j++)
                output[c++] = arr[i][j];
        }
 
        // sort the array
        Arrays.sort(output);
    }
 
    // A utility function to print array elements
    public static void printArray(int[] arr, int size)
    {
        for (int i = 0; i < size; i++)
            System.out.print(arr[i] + " ");
    }
   
    // Driver program to test above functions
    public static void main(String[] args)
    {
        int[][] arr = { { 2, 6, 12, 34 },
                        { 1, 9, 20, 1000 },
                        { 23, 34, 90, 2000 } };
        int k = 4;
        int n = 3;
        int[] output = new int[n * k];
 
        mergeKArrays(arr, n, output);
 
        System.out.println("Merged array is ");
        printArray(output, n * k);
    }
}


C#
// C# program to merge k sorted arrays of size n each.
using System;
public class GFG
{
 
  // This function takes an array of arrays as an argument
  // and
  // All arrays are assumed to be sorted. It merges them
  // together and prints the readonly sorted output.
  public static void mergeKArrays(int[,] arr, int a,
                                  int[] output)
  {
    int c = 0;
 
    // traverse the matrix
    for (int i = 0; i < a; i++)
    {
      for (int j = 0; j < 4; j++)
        output[c++] = arr[i,j];
    }
 
    // sort the array
    Array.Sort(output);
  }
 
  // A utility function to print array elements
  public static void printArray(int[] arr, int size)
  {
    for (int i = 0; i < size; i++)
      Console.Write(arr[i] + " ");
  }
 
  // Driver program to test above functions
  public static void Main(String[] args)
  {
    int[,] arr = { { 2, 6, 12, 34 },
                  { 1, 9, 20, 1000 },
                  { 23, 34, 90, 2000 } };
    int k = 4;
    int n = 3;
    int[] output = new int[n * k];
    mergeKArrays(arr, n, output);
    Console.WriteLine("Merged array is ");
    printArray(output, n * k);
  }
}
 
// This code is contributed by Rajput-Ji


CPP14
// C++ program to merge k sorted arrays of size n each.
#include
using namespace std;
#define n 4
 
// Merge arr1[0..n1-1] and arr2[0..n2-1] into
// arr3[0..n1+n2-1]
void mergeArrays(int arr1[], int arr2[], int n1,
                             int n2, int arr3[])
{
    int i = 0, j = 0, k = 0;
   
    // Traverse both array
    while (i


Java
// Java program to merge k sorted arrays of size n each.
import java.util.*;
 
class GFG{
  static final int n = 4;
 
  // Merge arr1[0..n1-1] and arr2[0..n2-1] into
  // arr3[0..n1+n2-1]
  static void mergeArrays(int arr1[], int arr2[], int n1,
                          int n2, int arr3[])
  {
    int i = 0, j = 0, k = 0;
 
    // Traverse both array
    while (i


C++
// C++ program to merge k sorted
// arrays of size n each.
#include
using namespace std;
 
#define n 4
 
// A min-heap node
struct MinHeapNode
{
// The element to be stored
    int element;
 
// index of the array from which the element is taken
    int i;
 
// index of the next element to be picked from the array
    int j;
};
 
// Prototype of a utility function to swap two min-heap nodes
void swap(MinHeapNode *x, MinHeapNode *y);
 
// A class for Min Heap
class MinHeap
{
 
// pointer to array of elements in heap
    MinHeapNode *harr;
 
// size of min heap
    int heap_size;
public:
    // Constructor: creates a min heap of given size
    MinHeap(MinHeapNode a[], int size);
 
    // to heapify a subtree with root at given index
    void MinHeapify(int );
 
    // to get index of left child of node at index i
    int left(int i) { return (2*i + 1); }
 
    // to get index of right child of node at index i
    int right(int i) { return (2*i + 2); }
 
    // to get the root
    MinHeapNode getMin() { return harr[0]; }
 
    // to replace root with new node x and heapify() new root
    void replaceMin(MinHeapNode x) { harr[0] = x;  MinHeapify(0); }
};
 
// This function takes an array of arrays as an argument and
// All arrays are assumed to be sorted. It merges them together
// and prints the final sorted output.
int *mergeKArrays(int arr[][n], int k)
{
 
// To store output array
    int *output = new int[n*k]; 
 
    // Create a min heap with k heap nodes.
    // Every heap node has first element of an array
    MinHeapNode *harr = new MinHeapNode[k];
    for (int i = 0; i < k; i++)
    {
 
// Store the first element
        harr[i].element = arr[i][0];
 
// index of array
        harr[i].i = i;
 
 // Index of next element to be stored from the array
        harr[i].j = 1;
    }
 
// Create the heap
    MinHeap hp(harr, k);
 
    // Now one by one get the minimum element from min
    // heap and replace it with next element of its array
    for (int count = 0; count < n*k; count++)
    {
        // Get the minimum element and store it in output
        MinHeapNode root = hp.getMin();
        output[count] = root.element;
 
        // Find the next elelement that will replace current
        // root of heap. The next element belongs to same
        // array as the current root.
        if (root.j < n)
        {
            root.element = arr[root.i][root.j];
            root.j += 1;
        }
        // If root was the last element of its array
// INT_MAX is for infinite       
else root.element =  INT_MAX;
 
        // Replace root with next element of array
        hp.replaceMin(root);
    }
 
    return output;
}
 
// FOLLOWING ARE IMPLEMENTATIONS OF
// STANDARD MIN HEAP METHODS FROM CORMEN BOOK
// Constructor: Builds a heap from a given
// array a[] of given size
MinHeap::MinHeap(MinHeapNode a[], int size)
{
    heap_size = size;
    harr = a;  // store address of array
    int i = (heap_size - 1)/2;
    while (i >= 0)
    {
        MinHeapify(i);
        i--;
    }
}
 
// A recursive method to heapify a
// subtree with root at given index.
// This method assumes that the subtrees
// are already heapified
void MinHeap::MinHeapify(int i)
{
    int l = left(i);
    int r = right(i);
    int smallest = i;
    if (l < heap_size && harr[l].element < harr[i].element)
        smallest = l;
    if (r < heap_size && harr[r].element < harr[smallest].element)
        smallest = r;
    if (smallest != i)
    {
        swap(&harr[i], &harr[smallest]);
        MinHeapify(smallest);
    }
}
 
// A utility function to swap two elements
void swap(MinHeapNode *x, MinHeapNode *y)
{
    MinHeapNode temp = *x;  *x = *y;  *y = temp;
}
 
// A utility function to print array elements
void printArray(int arr[], int size)
{
   for (int i=0; i < size; i++)
       cout << arr[i] << " ";
}
 
// Driver program to test above functions
int main()
{
    // Change n at the top to change number of elements
    // in an array
    int arr[][n] =  {{2, 6, 12, 34},
                     {1, 9, 20, 1000},
                     {23, 34, 90, 2000}};
    int k = sizeof(arr)/sizeof(arr[0]);
 
    int *output = mergeKArrays(arr, k);
 
    cout << "Merged array is " << endl;
    printArray(output, n*k);
 
    return 0;
}


Java
// Java program to merge k sorted
// arrays of size n each.
 
// A min heap node
class MinHeapNode
{
    int element; // The element to be stored
     
     // index of the array from
     // which the element is taken
    int i;
     
    // index of the next element
    // to be picked from array
    int j;
 
    public MinHeapNode(int element, int i, int j)
    {
        this.element = element;
        this.i = i;
        this.j = j;
    }
};
 
// A class for Min Heap
class MinHeap
{
    MinHeapNode[] harr; // Array of elements in heap
    int heap_size; // Current number of elements in min heap
 
    // Constructor: Builds a heap from
    // a given array a[] of given size
    public MinHeap(MinHeapNode a[], int size)
    {
        heap_size = size;
        harr = a;
        int i = (heap_size - 1)/2;
        while (i >= 0)
        {
            MinHeapify(i);
            i--;
        }
    }
 
    // A recursive method to heapify a subtree
    // with the root at given index This method
    // assumes that the subtrees are already heapified
    void MinHeapify(int i)
    {
        int l = left(i);
        int r = right(i);
        int smallest = i;
        if (l < heap_size && harr[l].element < harr[i].element)
            smallest = l;
        if (r < heap_size && harr[r].element < harr[smallest].element)
            smallest = r;
        if (smallest != i)
        {
            swap(harr, i, smallest);
            MinHeapify(smallest);
        }
    }
 
    // to get index of left child of node at index i
    int left(int i) { return (2*i + 1); }
 
    // to get index of right child of node at index i
    int right(int i) { return (2*i + 2); }
 
    // to get the root
    MinHeapNode getMin()
    {
        if(heap_size <= 0)
        {
            System.out.println("Heap underflow");
            return null;
        }
        return harr[0];
    }
 
    // to replace root with new node
    // "root" and heapify() new root
    void replaceMin(MinHeapNode root) {
        harr[0] = root;
        MinHeapify(0);
    }
 
    // A utility function to swap two min heap nodes
    void swap(MinHeapNode[] arr, int i, int j) {
        MinHeapNode temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
 
    // A utility function to print array elements
    static void printArray(int[] arr) {
        for(int i : arr)
            System.out.print(i + " ");
        System.out.println();
    }
 
    // This function takes an array of
    // arrays as an argument and All
    // arrays are assumed to be sorted.
    // It merges them together and
    // prints the final sorted output.
    static void mergeKSortedArrays(int[][] arr, int k)
    {
        MinHeapNode[] hArr = new MinHeapNode[k];
        int resultSize = 0;
        for(int i = 0; i < arr.length; i++)
        {
            MinHeapNode node = new MinHeapNode(arr[i][0],i,1);
            hArr[i] = node;
            resultSize += arr[i].length;
        }
 
        // Create a min heap with k heap nodes. Every heap node
        // has first element of an array
        MinHeap mh = new MinHeap(hArr, k);
 
        int[] result = new int[resultSize];     // To store output array
 
        // Now one by one get the minimum element from min
        // heap and replace it with next element of its array
        for(int i = 0; i < resultSize; i++)
        {
 
            // Get the minimum element and store it in result
            MinHeapNode root = mh.getMin();
            result[i] = root.element;
 
            // Find the next element that will replace current
            // root of heap. The next element belongs to same
            // array as the current root.
            if(root.j < arr[root.i].length)
                root.element = arr[root.i][root.j++];
            // If root was the last element of its array
            else
                root.element = Integer.MAX_VALUE;
 
            // Replace root with next element of array
            mh.replaceMin(root);
        }
 
        printArray(result);
 
    }
 
    // Driver code
    public static void main(String args[]){
        int[][] arr= {{2, 6, 12, 34},
                {1, 9, 20, 1000},
                {23, 34, 90, 2000}};
 
        System.out.println("Merged array is :");
 
        mergeKSortedArrays(arr,arr.length);
    }
};
 
// This code is contributed by shubham96301


C#
// C# program to merge k sorted
// arrays of size n each.
using System;
 
// A min heap node
public class MinHeapNode
{
    public int element; // The element to be stored
     
    // index of the array from
    // which the element is taken
    public int i;
     
    // index of the next element
    // to be picked from array
    public int j;
 
    public MinHeapNode(int element, int i, int j)
    {
        this.element = element;
        this.i = i;
        this.j = j;
    }
};
 
// A class for Min Heap
public class MinHeap
{
    MinHeapNode[] harr; // Array of elements in heap
    int heap_size; // Current number of elements in min heap
 
    // Constructor: Builds a heap from
    // a given array a[] of given size
    public MinHeap(MinHeapNode []a, int size)
    {
        heap_size = size;
        harr = a;
        int i = (heap_size - 1) / 2;
        while (i >= 0)
        {
            MinHeapify(i);
            i--;
        }
    }
 
    // A recursive method to heapify a subtree
    // with the root at given index This method
    // assumes that the subtrees are already heapified
    void MinHeapify(int i)
    {
        int l = left(i);
        int r = right(i);
        int smallest = i;
        if (l < heap_size &&
            harr[l].element < harr[i].element)
            smallest = l;
        if (r < heap_size &&
            harr[r].element < harr[smallest].element)
            smallest = r;
        if (smallest != i)
        {
            swap(harr, i, smallest);
            MinHeapify(smallest);
        }
    }
 
    // to get index of left child of node at index i
    int left(int i) { return (2 * i + 1); }
 
    // to get index of right child of node at index i
    int right(int i) { return (2 * i + 2); }
 
    // to get the root
    MinHeapNode getMin()
    {
        if(heap_size <= 0)
        {
            Console.WriteLine("Heap underflow");
            return null;
        }
        return harr[0];
    }
 
    // to replace root with new node
    // "root" and heapify() new root
    void replaceMin(MinHeapNode root)
    {
        harr[0] = root;
        MinHeapify(0);
    }
 
    // A utility function to swap two min heap nodes
    void swap(MinHeapNode[] arr, int i, int j)
    {
        MinHeapNode temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
 
    // A utility function to print array elements
    static void printArray(int[] arr)
    {
        foreach(int i in arr)
            Console.Write(i + " ");
        Console.WriteLine();
    }
 
    // This function takes an array of
    // arrays as an argument and All
    // arrays are assumed to be sorted.
    // It merges them together and
    // prints the final sorted output.
    static void mergeKSortedArrays(int[,] arr, int k)
    {
        MinHeapNode[] hArr = new MinHeapNode[k];
        int resultSize = 0;
        for(int i = 0; i < arr.GetLength(0); i++)
        {
            MinHeapNode node = new MinHeapNode(arr[i, 0], i, 1);
            hArr[i] = node;
            resultSize += arr.GetLength(1);
        }
 
        // Create a min heap with k heap nodes.
        // Every heap node has first element of an array
        MinHeap mh = new MinHeap(hArr, k);
 
        int[] result = new int[resultSize];     // To store output array
 
        // Now one by one get the minimum element
        // from min heap and replace it with
        // next element of its array
        for(int i = 0; i < resultSize; i++)
        {
 
            // Get the minimum element and
            // store it in result
            MinHeapNode root = mh.getMin();
            result[i] = root.element;
 
            // Find the next element that will
            // replace current root of heap.
            // The next element belongs to same
            // array as the current root.
            if(root.j < arr.GetLength(1))
                root.element = arr[root.i,root.j++];
                 
            // If root was the last element of its array
            else
                root.element = int.MaxValue;
 
            // Replace root with next element of array
            mh.replaceMin(root);
        }
        printArray(result);
    }
 
    // Driver code
    public static void Main(String []args)
    {
        int[,] arr = {{2, 6, 12, 34},
                      {1, 9, 20, 1000},
                      {23, 34, 90, 2000}};
 
        Console.WriteLine("Merged array is :");
 
        mergeKSortedArrays(arr, arr.GetLength(0));
    }
};
 
// This code is contributed by 29AjayKumar


输出:
Merged array is 
1 2 6 9 12 20 23 34 34 90 1000 2000
  • 复杂度分析:
    • 时间复杂度: O(n * k * log(n * k))。
      因为结果数组的大小为N * k。
    • 空间复杂度: O(n * k),输出数组的大小为n * k。

高效的方法该过程可能始于将数组合并为两个一组。第一次合并后,我们有k / 2个数组。再次合并成组的数组,现在我们有了k / 4个数组。这类似于合并排序。将k个数组分成两等分,包含相等数量的数组,直到一个组中有两个数组。然后以自底向上的方式合并阵列。

  • 算法:
    1. 创建一个递归函数,该函数接受k个数组并返回输出数组。
    2. 在递归函数,如果k的值为1,则返回该数组;否则,如果k的值为2,则在线性时间内合并两个数组并返回该数组。
    3. 如果k的值大于2,然后除以该组k个元素的成相等的两半,并递归地调用函数,即,0到K / 2阵列中的一个递归函数以及k / 2到k阵列中的另一个递归函数。
    4. 打印输出数组。
  • 执行:

CPP14

// C++ program to merge k sorted arrays of size n each.
#include
using namespace std;
#define n 4
 
// Merge arr1[0..n1-1] and arr2[0..n2-1] into
// arr3[0..n1+n2-1]
void mergeArrays(int arr1[], int arr2[], int n1,
                             int n2, int arr3[])
{
    int i = 0, j = 0, k = 0;
   
    // Traverse both array
    while (i

Java

// Java program to merge k sorted arrays of size n each.
import java.util.*;
 
class GFG{
  static final int n = 4;
 
  // Merge arr1[0..n1-1] and arr2[0..n2-1] into
  // arr3[0..n1+n2-1]
  static void mergeArrays(int arr1[], int arr2[], int n1,
                          int n2, int arr3[])
  {
    int i = 0, j = 0, k = 0;
 
    // Traverse both array
    while (i
输出:
Merged array is 
1 2 6 9 12 20 23 34 34 90 1000 2000
  • 复杂度分析:
    • 时间复杂度: O(n * k * log k)。
      存在log k个级别,因为在每个级别中,将k个数组分为两半,并且在每个级别上遍历k个数组。因此,时间复杂度为O(n * k)。
    • 空间复杂度: O(n * k * log k)。
      在每个级别中都需要O(n * k)空间,因此空间复杂度为O(n * k * log k)。

替代有效方法:想法是使用Min Heap。这种基于MinHeap的解决方案具有相同的时间复杂度,即O(NK log K)。但是对于不同大小的阵列,此解决方案效果更好。该过程必须从创建MinHeap并插入所有k个数组的第一个元素开始。删除Minheap的根元素,并将其放在输出数组中,然后从已删除元素的数组中插入下一个元素。为了获得结果,该步骤必须继续进行,直到MinHeap中没有元素为止。
MinHeap: Min-Heap是完整的二叉树,其中每个内部节点中的值小于或等于该节点的子级中的值。将堆的元素映射到数组很简单:如果节点存储在索引k处,则其左子节点存储在索引2k + 1处,其右子节点存储在索引2k + 2处。

  • 算法:
    1. 创建一个最小堆,并插入所有k个数组的第一个元素。
    2. 运行循环,直到MinHeap的大小大于零。
    3. 删除MinHeap的顶部元素,然后打印该元素。
    4. 现在,从移除的元素所属的同一数组中插入下一个元素。
    5. 如果数组中没有更多元素,则将root替换为infinite。替换根之后,堆放树。
  • 执行:

C++

// C++ program to merge k sorted
// arrays of size n each.
#include
using namespace std;
 
#define n 4
 
// A min-heap node
struct MinHeapNode
{
// The element to be stored
    int element;
 
// index of the array from which the element is taken
    int i;
 
// index of the next element to be picked from the array
    int j;
};
 
// Prototype of a utility function to swap two min-heap nodes
void swap(MinHeapNode *x, MinHeapNode *y);
 
// A class for Min Heap
class MinHeap
{
 
// pointer to array of elements in heap
    MinHeapNode *harr;
 
// size of min heap
    int heap_size;
public:
    // Constructor: creates a min heap of given size
    MinHeap(MinHeapNode a[], int size);
 
    // to heapify a subtree with root at given index
    void MinHeapify(int );
 
    // to get index of left child of node at index i
    int left(int i) { return (2*i + 1); }
 
    // to get index of right child of node at index i
    int right(int i) { return (2*i + 2); }
 
    // to get the root
    MinHeapNode getMin() { return harr[0]; }
 
    // to replace root with new node x and heapify() new root
    void replaceMin(MinHeapNode x) { harr[0] = x;  MinHeapify(0); }
};
 
// This function takes an array of arrays as an argument and
// All arrays are assumed to be sorted. It merges them together
// and prints the final sorted output.
int *mergeKArrays(int arr[][n], int k)
{
 
// To store output array
    int *output = new int[n*k]; 
 
    // Create a min heap with k heap nodes.
    // Every heap node has first element of an array
    MinHeapNode *harr = new MinHeapNode[k];
    for (int i = 0; i < k; i++)
    {
 
// Store the first element
        harr[i].element = arr[i][0];
 
// index of array
        harr[i].i = i;
 
 // Index of next element to be stored from the array
        harr[i].j = 1;
    }
 
// Create the heap
    MinHeap hp(harr, k);
 
    // Now one by one get the minimum element from min
    // heap and replace it with next element of its array
    for (int count = 0; count < n*k; count++)
    {
        // Get the minimum element and store it in output
        MinHeapNode root = hp.getMin();
        output[count] = root.element;
 
        // Find the next elelement that will replace current
        // root of heap. The next element belongs to same
        // array as the current root.
        if (root.j < n)
        {
            root.element = arr[root.i][root.j];
            root.j += 1;
        }
        // If root was the last element of its array
// INT_MAX is for infinite       
else root.element =  INT_MAX;
 
        // Replace root with next element of array
        hp.replaceMin(root);
    }
 
    return output;
}
 
// FOLLOWING ARE IMPLEMENTATIONS OF
// STANDARD MIN HEAP METHODS FROM CORMEN BOOK
// Constructor: Builds a heap from a given
// array a[] of given size
MinHeap::MinHeap(MinHeapNode a[], int size)
{
    heap_size = size;
    harr = a;  // store address of array
    int i = (heap_size - 1)/2;
    while (i >= 0)
    {
        MinHeapify(i);
        i--;
    }
}
 
// A recursive method to heapify a
// subtree with root at given index.
// This method assumes that the subtrees
// are already heapified
void MinHeap::MinHeapify(int i)
{
    int l = left(i);
    int r = right(i);
    int smallest = i;
    if (l < heap_size && harr[l].element < harr[i].element)
        smallest = l;
    if (r < heap_size && harr[r].element < harr[smallest].element)
        smallest = r;
    if (smallest != i)
    {
        swap(&harr[i], &harr[smallest]);
        MinHeapify(smallest);
    }
}
 
// A utility function to swap two elements
void swap(MinHeapNode *x, MinHeapNode *y)
{
    MinHeapNode temp = *x;  *x = *y;  *y = temp;
}
 
// A utility function to print array elements
void printArray(int arr[], int size)
{
   for (int i=0; i < size; i++)
       cout << arr[i] << " ";
}
 
// Driver program to test above functions
int main()
{
    // Change n at the top to change number of elements
    // in an array
    int arr[][n] =  {{2, 6, 12, 34},
                     {1, 9, 20, 1000},
                     {23, 34, 90, 2000}};
    int k = sizeof(arr)/sizeof(arr[0]);
 
    int *output = mergeKArrays(arr, k);
 
    cout << "Merged array is " << endl;
    printArray(output, n*k);
 
    return 0;
}

Java

// Java program to merge k sorted
// arrays of size n each.
 
// A min heap node
class MinHeapNode
{
    int element; // The element to be stored
     
     // index of the array from
     // which the element is taken
    int i;
     
    // index of the next element
    // to be picked from array
    int j;
 
    public MinHeapNode(int element, int i, int j)
    {
        this.element = element;
        this.i = i;
        this.j = j;
    }
};
 
// A class for Min Heap
class MinHeap
{
    MinHeapNode[] harr; // Array of elements in heap
    int heap_size; // Current number of elements in min heap
 
    // Constructor: Builds a heap from
    // a given array a[] of given size
    public MinHeap(MinHeapNode a[], int size)
    {
        heap_size = size;
        harr = a;
        int i = (heap_size - 1)/2;
        while (i >= 0)
        {
            MinHeapify(i);
            i--;
        }
    }
 
    // A recursive method to heapify a subtree
    // with the root at given index This method
    // assumes that the subtrees are already heapified
    void MinHeapify(int i)
    {
        int l = left(i);
        int r = right(i);
        int smallest = i;
        if (l < heap_size && harr[l].element < harr[i].element)
            smallest = l;
        if (r < heap_size && harr[r].element < harr[smallest].element)
            smallest = r;
        if (smallest != i)
        {
            swap(harr, i, smallest);
            MinHeapify(smallest);
        }
    }
 
    // to get index of left child of node at index i
    int left(int i) { return (2*i + 1); }
 
    // to get index of right child of node at index i
    int right(int i) { return (2*i + 2); }
 
    // to get the root
    MinHeapNode getMin()
    {
        if(heap_size <= 0)
        {
            System.out.println("Heap underflow");
            return null;
        }
        return harr[0];
    }
 
    // to replace root with new node
    // "root" and heapify() new root
    void replaceMin(MinHeapNode root) {
        harr[0] = root;
        MinHeapify(0);
    }
 
    // A utility function to swap two min heap nodes
    void swap(MinHeapNode[] arr, int i, int j) {
        MinHeapNode temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
 
    // A utility function to print array elements
    static void printArray(int[] arr) {
        for(int i : arr)
            System.out.print(i + " ");
        System.out.println();
    }
 
    // This function takes an array of
    // arrays as an argument and All
    // arrays are assumed to be sorted.
    // It merges them together and
    // prints the final sorted output.
    static void mergeKSortedArrays(int[][] arr, int k)
    {
        MinHeapNode[] hArr = new MinHeapNode[k];
        int resultSize = 0;
        for(int i = 0; i < arr.length; i++)
        {
            MinHeapNode node = new MinHeapNode(arr[i][0],i,1);
            hArr[i] = node;
            resultSize += arr[i].length;
        }
 
        // Create a min heap with k heap nodes. Every heap node
        // has first element of an array
        MinHeap mh = new MinHeap(hArr, k);
 
        int[] result = new int[resultSize];     // To store output array
 
        // Now one by one get the minimum element from min
        // heap and replace it with next element of its array
        for(int i = 0; i < resultSize; i++)
        {
 
            // Get the minimum element and store it in result
            MinHeapNode root = mh.getMin();
            result[i] = root.element;
 
            // Find the next element that will replace current
            // root of heap. The next element belongs to same
            // array as the current root.
            if(root.j < arr[root.i].length)
                root.element = arr[root.i][root.j++];
            // If root was the last element of its array
            else
                root.element = Integer.MAX_VALUE;
 
            // Replace root with next element of array
            mh.replaceMin(root);
        }
 
        printArray(result);
 
    }
 
    // Driver code
    public static void main(String args[]){
        int[][] arr= {{2, 6, 12, 34},
                {1, 9, 20, 1000},
                {23, 34, 90, 2000}};
 
        System.out.println("Merged array is :");
 
        mergeKSortedArrays(arr,arr.length);
    }
};
 
// This code is contributed by shubham96301

C#

// C# program to merge k sorted
// arrays of size n each.
using System;
 
// A min heap node
public class MinHeapNode
{
    public int element; // The element to be stored
     
    // index of the array from
    // which the element is taken
    public int i;
     
    // index of the next element
    // to be picked from array
    public int j;
 
    public MinHeapNode(int element, int i, int j)
    {
        this.element = element;
        this.i = i;
        this.j = j;
    }
};
 
// A class for Min Heap
public class MinHeap
{
    MinHeapNode[] harr; // Array of elements in heap
    int heap_size; // Current number of elements in min heap
 
    // Constructor: Builds a heap from
    // a given array a[] of given size
    public MinHeap(MinHeapNode []a, int size)
    {
        heap_size = size;
        harr = a;
        int i = (heap_size - 1) / 2;
        while (i >= 0)
        {
            MinHeapify(i);
            i--;
        }
    }
 
    // A recursive method to heapify a subtree
    // with the root at given index This method
    // assumes that the subtrees are already heapified
    void MinHeapify(int i)
    {
        int l = left(i);
        int r = right(i);
        int smallest = i;
        if (l < heap_size &&
            harr[l].element < harr[i].element)
            smallest = l;
        if (r < heap_size &&
            harr[r].element < harr[smallest].element)
            smallest = r;
        if (smallest != i)
        {
            swap(harr, i, smallest);
            MinHeapify(smallest);
        }
    }
 
    // to get index of left child of node at index i
    int left(int i) { return (2 * i + 1); }
 
    // to get index of right child of node at index i
    int right(int i) { return (2 * i + 2); }
 
    // to get the root
    MinHeapNode getMin()
    {
        if(heap_size <= 0)
        {
            Console.WriteLine("Heap underflow");
            return null;
        }
        return harr[0];
    }
 
    // to replace root with new node
    // "root" and heapify() new root
    void replaceMin(MinHeapNode root)
    {
        harr[0] = root;
        MinHeapify(0);
    }
 
    // A utility function to swap two min heap nodes
    void swap(MinHeapNode[] arr, int i, int j)
    {
        MinHeapNode temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
 
    // A utility function to print array elements
    static void printArray(int[] arr)
    {
        foreach(int i in arr)
            Console.Write(i + " ");
        Console.WriteLine();
    }
 
    // This function takes an array of
    // arrays as an argument and All
    // arrays are assumed to be sorted.
    // It merges them together and
    // prints the final sorted output.
    static void mergeKSortedArrays(int[,] arr, int k)
    {
        MinHeapNode[] hArr = new MinHeapNode[k];
        int resultSize = 0;
        for(int i = 0; i < arr.GetLength(0); i++)
        {
            MinHeapNode node = new MinHeapNode(arr[i, 0], i, 1);
            hArr[i] = node;
            resultSize += arr.GetLength(1);
        }
 
        // Create a min heap with k heap nodes.
        // Every heap node has first element of an array
        MinHeap mh = new MinHeap(hArr, k);
 
        int[] result = new int[resultSize];     // To store output array
 
        // Now one by one get the minimum element
        // from min heap and replace it with
        // next element of its array
        for(int i = 0; i < resultSize; i++)
        {
 
            // Get the minimum element and
            // store it in result
            MinHeapNode root = mh.getMin();
            result[i] = root.element;
 
            // Find the next element that will
            // replace current root of heap.
            // The next element belongs to same
            // array as the current root.
            if(root.j < arr.GetLength(1))
                root.element = arr[root.i,root.j++];
                 
            // If root was the last element of its array
            else
                root.element = int.MaxValue;
 
            // Replace root with next element of array
            mh.replaceMin(root);
        }
        printArray(result);
    }
 
    // Driver code
    public static void Main(String []args)
    {
        int[,] arr = {{2, 6, 12, 34},
                      {1, 9, 20, 1000},
                      {23, 34, 90, 2000}};
 
        Console.WriteLine("Merged array is :");
 
        mergeKSortedArrays(arr, arr.GetLength(0));
    }
};
 
// This code is contributed by 29AjayKumar
输出:
Merged array is 
1 2 6 9 12 20 23 34 34 90 1000 2000
  • 复杂度分析:
    • 时间复杂度: O(n * k * log k),在最小堆中插入和删除需要log k时间。因此,总时间复杂度为O(n * k * log k)
    • 空间复杂度: O(k),如果未存储输出,则所需的唯一空间是k个元素的最小堆。因此,空间复杂度为O(k)。