还是基于merge的思想
方法1:
依次取每个数组的首个元素进行比较,pop出最大者放入结果数组,直到所有数据处理完毕。这个做法每得到一个结果就需要比较K次。
package Level3;
import java.util.ArrayList;
import Utility.ListNode;
/**
* Merge k Sorted Lists
* Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
*
*/
public class S23 {
public static void main(String[] args) {
int[] a = {1,2,3};
ListNode aLN = ListNode.create(a);
ArrayList<ListNode> lists = new ArrayList<ListNode>();
lists.add(aLN);
ListNode h = mergeKLists(lists);
h.print();
}
public static ListNode mergeKLists(ArrayList<ListNode> lists) {
ListNode mergedHead = new ListNode(-1); // 利用dummy作为表头
ListNode[] ptrs = new ListNode[lists.size()]; // 指针指向每一个ListNode
for(int i=0; i<lists.size(); i++){ // 初始化指针数组
ptrs[i] = lists.get(i);
}
ListNode mergedCur = mergedHead;
boolean run = true;
while(true){
run = false; // run用来检测是否所有的链表都已经遍历完了,即指针为null
int val = Integer.MAX_VALUE;
int minIndex = 0;
for(int j=0; j<ptrs.length; j++){ // 找到最小的那一个表头
if(ptrs[j] != null){
run = true;
if(ptrs[j].val < val){
val = ptrs[j].val;
minIndex = j;
}
}
}
if(!run){ // 及时退出
break;
}
mergedCur.next = new ListNode(ptrs[minIndex].val); // 更新merged链表和最小的表头指针
ptrs[minIndex] = ptrs[minIndex].next;
mergedCur = mergedCur.next;
}
return mergedHead.next;
}
}
这道题有更快的利用堆的多路归并做法:
方法2:
建立含有K个元素的最大堆,堆的初值分别来自K个数组的首个元素。堆的每个结点同时记录了如下信息:1) 该结点的取值;2) 来自哪个数组;3) 该取值位于数组中的位置。
每次pop出最大堆的堆顶(pop出后要调整保持最大堆),加入结果数组。同时可以知道该元素的所在数组以及位置,把其在数组中下一个位置的元素insert进最大堆。直到所有数据处理完毕。
pop出堆顶的最坏情况复杂度是log(K),insert一个元素进最大堆的最坏情况复杂度是log(K),因此每得到一个结果在最坏情况下需要比较2logK次
用递归做会TLE,所以第二遍还是用迭代法做
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode mergeKLists(List<ListNode> lists) {
if (lists.size() == 0) {
return null;
}
ListNode merged = new ListNode(0);
ListNode cur = merged;
ListNode[] ptrs = new ListNode[lists.size()];
for(int i=0; i<lists.size(); i++) {
ptrs[i] = lists.get(i);
}
while(true) {
int minIndex = -1;
int min = Integer.MAX_VALUE;
for(int i=0; i<ptrs.length; i++) {
if(ptrs[i] != null && ptrs[i].val < min) {
min = ptrs[i].val;
minIndex = i;
}
}
if(minIndex == -1) {
break;
}
cur.next = new ListNode(min);
ptrs[minIndex] = ptrs[minIndex].next;
cur = cur.next;
}
return merged.next;
}
}