Merge k Sorted Arrays【合并k个有序数组】【优先队列】
Given k sorted integer arrays, merge them into one sorted array.
Example Given 3 sorted arrays:
[
[1, 3, 5, 7],
[2, 4, 6],
[0, 8, 9, 10, 11]
]
return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].
Challenge Do it in O(N log k).
N is the total number of integers. k is the number of arrays.
Solution:
创建一个大小为N的数组保存最后的结果
数组本身已经从小到大排好序,所以我们只需创建一个大小为k的最小堆,堆中初始元素为k个数组中的每个数组的第一个元素,每次从堆中取出最小元素(堆顶元素),并将其存入输出数组中,将堆顶元素所在行的下一元素加入堆,重新排列出堆顶元素,时间复杂度为logk,总共N个元素,所以总体时间复杂度是Nlogk
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
class Element{
public int row,col,val;
public Element(int row, int col, int val) {
this.row = row;
this.col = col;
this.val = val;
}
}
public class Main {
private Comparator<Element> MyCmp = new Comparator<Element>() {
@Override //升序
public int compare(Element o1, Element o2) {
return o1.val - o2.val;
}
};
public int[] mergeKSortedArrays(int[][] arr) {
if(arr == null) {
return new int[0];
}
int sum = 0;
Queue<Element> q = new PriorityQueue<Element>(
arr.length,MyCmp);
for(int i = 0; i < arr.length; i++) {
if(arr[i].length > 0) {
Element e = new Element(i, 0, arr[i][0]);
q.add(e);
sum += arr[i].length; //记录结果数组总长度
}
}
int[] res = new int[sum];
int idx = 0;
while(!q.isEmpty()) {
Element e = q.poll(); //弹出堆顶最小值
res[idx++] = e.val;
// 当前结点被 PriorityQueue 抛出来后,当前行的第二个结点加入 PriorityQueue
if(e.col + 1 < arr[e.row].length) { //将当前最小所在数组的下一个元素存入pq
q.add(new Element(e.row, e.col+1, arr[e.row][e.col+1]));
}
}
return res;
}
public static void main(String[] args) {
Main m = new Main();
int[][] arr = {{1, 3, 5, 7},{2, 4, 6},{0, 8, 9, 10, 11}};
int[] res = m.mergeKSortedArrays(arr);
for(int i=0; i<res.length; i++) {
System.out.print(res[i] + " ");
}
}
}
/*
Input:
[
[1, 3, 5, 7],
[2, 4, 6],
[0, 8, 9, 10, 11]
]
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
*/
GG手写堆排序的写法;
// 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
PS:一面头条笔试