给定 k 个大小为 n 的排序数组,合并它们并打印排序后的输出。
例子:
Input:
k = 3, n = 4
arr[][] = { {1, 3, 5, 7},
{2, 4, 6, 8},
{0, 9, 10, 11}} ;
Output: 0 1 2 3 4 5 6 7 8 9 10 11
Explanation: The output array is a sorted array that contains all the elements of the input matrix.
Input:
k = 4, n = 4
arr[][] = { {1, 5, 6, 8},
{2, 4, 10, 12},
{3, 7, 9, 11},
{13, 14, 15, 16}} ;
Output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Explanation: The output array is a sorted array that contains all the elements of the input matrix.
朴素的方法:非常朴素的方法是创建一个大小为 n * k 的输出数组,然后将所有元素复制到输出数组中,然后进行排序。
- 算法:
- 创建一个大小为 n * k 的输出数组。
- 从头到尾遍历矩阵并将所有元素插入输出数组中。
- 排序并打印输出数组。
- 执行:
C++14
// 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
Javascript
C++14
// 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.
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 " + "\n");
printArray(output, n * k);
}
}
// This code is contributed by Rajput-Ji
Javascript
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。
- 时间复杂度: O(n*k*log(n*k))。
有效的方法该过程可能从将数组合并为两个一组开始。第一次合并后,我们有 k/2 个数组。再次按组合并数组,现在我们有 k/4 个数组。这类似于归并排序。将 k 个数组分成包含相同数量数组的两半,直到一组中有两个数组。然后以自底向上的方式合并数组。
- 算法:
- 创建一个递归函数,它接受 k 个数组并返回输出数组。
- 在递归函数,如果 k 的值为 1 则返回数组,否则如果 k 的值为 2 则在线性时间内合并两个数组并返回数组。
- 如果k的值大于2,然后除以该组k个元素的成相等的两半,并递归地调用函数,即,0到K / 2阵列中的一个递归函数以及k / 2到k阵列中的另一个递归函数。
- 打印输出数组。
- 执行:
C++14
// 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.
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 " + "\n");
printArray(output, n * k);
}
}
// This code is contributed by Rajput-Ji
Javascript
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)。
替代高效方法:这个想法是使用最小堆。这个基于 MinHeap 的解决方案具有相同的时间复杂度,即 O(NK log K)。但是对于不同且特定大小的数组,此解决方案效果更好。该过程必须从创建一个 MinHeap 并插入所有 k 个数组的第一个元素开始。移除 Minheap 的根元素并将其放入输出数组中,然后插入移除元素数组中的下一个元素。要获得结果,该步骤必须继续,直到 MinHeap 中没有元素为止。
MinHeap: Min-Heap 是一个完整的二叉树,其中每个内部节点中的值小于或等于该节点的子节点中的值。将堆的元素映射到数组是微不足道的:如果一个节点存储在索引 k 处,则其左子节点存储在索引 2k + 1 处,其右子节点存储在索引 2k + 2 处。
- 算法:
- 创建一个最小堆并插入所有 k 个数组的第一个元素。
- 运行一个循环,直到 MinHeap 的大小大于零。
- 删除 MinHeap 的顶部元素并打印该元素。
- 现在从删除元素所属的同一数组中插入下一个元素。
- 如果数组没有更多元素,则将root替换为infinite。替换root后,将树堆化。
执行:
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)。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。