合并k个排序数组|集1

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

null

例子:

输入: k=3,n=4 arr[][]={{1,3,5,7}, {2, 4, 6, 8}, {0, 9, 10, 11}} ; 输出: 0 1 2 3 4 5 6 7 8 9 10 11 说明: 输出数组是一个包含输入矩阵所有元素的排序数组。

输入: k=4,n=4 arr[][={{1,5,6,8}, {2, 4, 10, 12}, {3, 7, 9, 11}, {13, 14, 15, 16}} ; 输出: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 说明: 输出数组是一个包含输入矩阵所有元素的排序数组。

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

  • 算法:
    1. 创建大小为n*k的输出数组。
    2. 从头到尾遍历矩阵,并在输出数组中插入所有元素。
    3. 排序并打印输出数组。
  • 实施:

C++14

// C++ program to merge k sorted arrays of size n each.
#include<bits/stdc++.h>
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<a; i++)
{
for ( int j=0; j<n ;j++)
output=arr[i][j];
}
//sort the array
sort(output,output + n*a);
}
// 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[n*k];
mergeKArrays(arr, 3, output);
cout << "Merged array is " << endl;
printArray(output, n*k);
return 0;
}


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 = 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);
}
}


Python3

# Python program to merge k sorted arrays of size n each.
# 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.
def mergeKArrays(arr, a, output):
c = 0 ;
# traverse the matrix
for i in range (a):
for j in range ( 4 ):
output = arr[i][j];
c + = 1 ;
# sort the array
output.sort();
# A utility function to print array elements
def printArray(arr, size):
for i in range (size):
print (arr[i], end = " " );
# Driver program to test above functions
if __name__ = = '__main__' :
arr = [[ 2 , 6 , 12 , 34 ],[ 1 , 9 , 20 , 1000 ],[ 23 , 34 , 90 , 2000 ]] ;
k = 4 ;
n = 3 ;
output = [ 0 for i in range (n * k)];
mergeKArrays(arr, n, output);
print ( "Merged array is " );
printArray(output, n * k);
# This code is contributed by umadevi9616


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 = 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


Javascript

<script>
// Javascript program to merge k sorted
// arrays of size n each.
// 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.
function mergeKArrays(arr , a,  output)
{
var c = 0;
// traverse the matrix
for (i = 0; i < a; i++) {
for (j = 0; j < 4; j++)
output = arr[i][j];
}
// sort the array
output.sort((a,b)=>a-b);
}
// A utility function to print array elements
function printArray(arr , size) {
for (i = 0; i < size; i++)
document.write(arr[i] + " " );
}
// Driver program to test above functions
var arr = [ [ 2, 6, 12, 34 ],
[ 1, 9, 20, 1000 ],
[ 23, 34, 90, 2000 ] ];
var k = 4;
var n = 3;
var output = Array(n * k).fill(0);
mergeKArrays(arr, n, output);
document.write( "Merged array is " );
printArray(output, n * k);
// This code contributed by Rajput-Ji
</script>


输出:

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. 打印输出数组。
  • 实施:

C++14

// C++ program to merge k sorted arrays of size n each.
#include<bits/stdc++.h>
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<n1 && j <n2)
{
// Check if current element of first
// array is smaller than current element
// of second array. If yes, store first
// array element and increment first array
// index. Otherwise do same with second array
if (arr1[i] < arr2[j])
arr3[k++] = arr1[i++];
else
arr3[k++] = arr2[j++];
}
// Store remaining elements of first array
while (i < n1)
arr3[k++] = arr1[i++];
// Store remaining elements of second array
while (j < n2)
arr3[k++] = arr2[j++];
}
// 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 i, int j, int output[])
{
//if one array is in range
if (i==j)
{
for ( int p=0; p < n; p++)
output[p]=arr[i][p];
return ;
}
//if only two arrays are left them merge them
if (j-i==1)
{
mergeArrays(arr[i],arr[j],n,n,output);
return ;
}
//output arrays
int out1[n*(((i+j)/2)-i+1)],out2[n*(j-((i+j)/2))];
//divide the array into halves
mergeKArrays(arr,i,(i+j)/2,out1);
mergeKArrays(arr,(i+j)/2+1,j,out2);
//merge the output array
mergeArrays(out1,out2,n*(((i+j)/2)-i+1),n*(j-((i+j)/2)),output);
}
// 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[n*k];
mergeKArrays(arr,0,2, output);
cout << "Merged array is " << endl;
printArray(output, n*k);
return 0;
}


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<n1 && j <n2)
{
// Check if current element of first
// array is smaller than current element
// of second array. If yes, store first
// array element and increment first array
// index. Otherwise do same with second array
if (arr1[i] < arr2[j])
arr3[k++] = arr1[i++];
else
arr3[k++] = arr2[j++];
}
// Store remaining elements of first array
while (i < n1)
arr3[k++] = arr1[i++];
// Store remaining elements of second array
while (j < n2)
arr3[k++] = arr2[j++];
}
// A utility function to print array elements
static void printArray( int arr[], int size)
{
for ( int i = 0 ; i < size; i++)
System.out.print(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.
static void mergeKArrays( int arr[][], int i, int j, int output[])
{
// if one array is in range
if (i == j)
{
for ( int p = 0 ; p < n; p++)
output[p] = arr[i][p];
return ;
}
//if only two arrays are left them merge them
if (j - i == 1 )
{
mergeArrays(arr[i], arr[j], n, n, output);
return ;
}
//output arrays
int []out1 = new int [n*(((i + j) / 2 ) - i + 1 )];
int []out2 = new int [n*(j - ((i + j) / 2 ))];
//divide the array into halves
mergeKArrays(arr, i, (i + j) / 2 , out1);
mergeKArrays(arr, (i + j) / 2 + 1 , j, out2);
//merge the output array
mergeArrays(out1, out2, n * (((i + j) / 2 ) - i + 1 ), n * (j - ((i + j) / 2 )), output);
}
// Driver program to test above functions
public static void main(String[] args)
{
// Change n at the top to change number of elements
// in an array
int arr[][] =  {{ 2 , 6 , 12 , 34 },
{ 1 , 9 , 20 , 1000 },
{ 23 , 34 , 90 , 2000 }};
int k = arr.length;
int []output = new int [n*k];
mergeKArrays(arr, 0 , 2 , output);
System.out.print( "Merged array is " + "" );
printArray(output, n*k);
}
}
// This code is contributed by gauravrajput1


C#

// C# program to merge k sorted arrays of size n each.
using System;
class GFG{
static readonly int n = 4;
public static int [] GetRow( int [,] matrix, int row)
{
var rowLength = matrix.GetLength(1);
var rowVector = new int [rowLength];
for ( var i = 0; i < rowLength; i++)
rowVector[i] = matrix[row, i];
return rowVector;
}
// 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 < n1 && j < n2)
{
// Check if current element of first
// array is smaller than current element
// of second array. If yes, store first
// array element and increment first array
// index. Otherwise do same with second array
if (arr1[i] < arr2[j])
arr3[k++] = arr1[i++];
else
arr3[k++] = arr2[j++];
}
// Store remaining elements of first array
while (i < n1)
arr3[k++] = arr1[i++];
// Store remaining elements of second array
while (j < n2)
arr3[k++] = arr2[j++];
}
// A utility function to print array elements
static void printArray( int []arr, int size)
{
for ( int i = 0; i < size; i++)
Console.Write(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 readonly sorted output.
static void mergeKArrays( int [,]arr, int i,
int j, int []output)
{
// If one array is in range
if (i == j)
{
for ( int p = 0; p < n; p++)
output[p] = arr[i, p];
return ;
}
// If only two arrays are left them merge them
if (j - i == 1)
{
mergeArrays(GetRow(arr, i), GetRow(arr, j),
n, n, output);
return ;
}
// Output arrays
int []out1 = new int [n*(((i + j) / 2) - i + 1)];
int []out2 = new int [n*(j - ((i + j) / 2))];
// Divide the array into halves
mergeKArrays(arr, i, (i + j) / 2, out1);
mergeKArrays(arr, (i + j) / 2 + 1, j, out2);
// Merge the output array
mergeArrays(out1, out2, n * (((i + j) / 2) - i + 1),
n * (j - ((i + j) / 2)), output);
}
// Driver code
public static void Main(String[] args)
{
// Change n at the top to change number of elements
// in an array
int [,]arr =  { { 2, 6, 12, 34 },
{ 1, 9, 20, 1000 },
{ 23, 34, 90, 2000 } };
int k = arr.GetLength(0);
int []output = new int [n * k];
mergeKArrays(arr, 0, 2, output);
Console.Write( "Merged array is " + "" );
printArray(output, n * k);
}
}
// This code is contributed by Rajput-Ji


Javascript

<script>
// Javascript program to merge k
// sorted arrays of size n each.
let n =  4
// Merge arr1[0..n1-1] and arr2[0..n2-1] into
// arr3[0..n1+n2-1]
function mergeArrays(arr1, arr2, n1, n2, arr3)
{
let i = 0, j = 0, k = 0;
// Traverse both array
while (i < n1 && j < n2)
{
// Check if current element of first
// array is smaller than current element
// of second array. If yes, store first
// array element and increment first array
// index. Otherwise do same with second array
if (arr1[i] < arr2[j])
arr3[k++] = arr1[i++];
else
arr3[k++] = arr2[j++];
}
// Store remaining elements of first array
while (i < n1)
arr3[k++] = arr1[i++];
// Store remaining elements of second array
while (j < n2)
arr3[k++] = arr2[j++];
}
// A utility function to print array elements
function printArray(arr, size)
{
for (let i = 0; i < size; i++)
document.write(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.
function mergeKArrays(arr, i, j, output)
{
// If one array is in range
if (i == j)
{
for (let p = 0; p < n; p++)
output[p] = arr[i][p];
return ;
}
// If only two arrays are left
// them merge them
if (j - i == 1)
{
mergeArrays(arr[i], arr[j],
n, n, output);
return ;
}
// Output arrays
let out1 = new Array(n * (((i + j) / 2) - i + 1))
let out2 = new Array(n * (j - ((i + j) / 2)));
// Divide the array into halves
mergeKArrays(arr, i, (i + j) / 2, out1);
mergeKArrays(arr, (i + j) / 2 + 1, j, out2);
// Merge the output array
mergeArrays(out1, out2,
n * (((i + j) / 2) - i + 1),
n * (j - ((i + j) / 2)), output);
}
// Driver code
// Change n at the top to change number
// of elements in an array
let arr = [ [ 2, 6, 12, 34 ],
[ 1, 9, 20, 1000 ],
[ 23, 34, 90, 2000 ] ];
let k = arr.length;
let output = new Array(n * k);
mergeKArrays(arr, 0, 2, output);
document.write( "Merged array is " + "<br>" );
printArray(output, n * k);
// This code is contributed by Mayank Tyagi
</script>


输出:

Merged array is 1 2 6 9 12 20 23 34 34 90 1000 2000

复杂性分析:

  • 时间复杂性: O(n*k*logk)。 日志有k个级别,因为在每个级别中,k个数组被分成两半,在每个级别上,k个数组被遍历。所以时间复杂度是O(n*k)。
  • 空间复杂性: O(n*k*logk)。 在每个级别中都需要O(n*k)空间,因此空间复杂度为O(n*k*logk)。

其他有效方法: 这个想法是使用 最小堆 .这种基于MinHeap的解决方案具有与O(NK log K)相同的时间复杂度。但是为了一个 不同大小的阵列 ,此解决方案效果更好。这个过程必须从创建一个MinHeap并插入所有k数组的第一个元素开始。移除Minheap的根元素并将其放入输出数组,然后从移除的元素数组中插入下一个元素。要获得结果,该步骤必须继续,直到MinHeap中没有剩余的元素。

MinHeap: 最小堆是一个完整的二叉树,其中每个内部节点中的值小于或等于该节点的子节点中的值。将堆的元素映射到数组是很简单的:如果一个节点存储在索引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<bits/stdc++.h>
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 element 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*logk),在最小堆中插入和删除需要logk时间。所以总的时间复杂度是O(n*k*logk)
  • 空间复杂性: O(k),如果未存储输出,则所需的唯一空间是k个元素的最小堆。所以空间复杂度是O(k)。

合并k个排序数组|集合2(不同大小的数组) 幸亏 维涅什 感谢您提出这个问题和初步解决方案。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享