Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
JAVA
方法一
可以把输入看做一个二维数组,数组的每一行都是递增的,因此每次只找第一列中最小的元素放入结果链表的尾部,然后将该行后续的数字前移。结果超时
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode result = new ListNode(0);
ListNode tail = result;
int min;
int index;
boolean empty = false;
while(!empty){
empty = true;
min = Integer.MAX_VALUE;
index = 0;
for(int i = 0; i < lists.length; ++i){
if(lists[i] != null){
empty = false;
if(lists[i].val <= min){
min = lists[i].val;
index = i;
}
}
}
if(!empty){
tail.next = lists[index];
tail = tail.next;
lists[index] = lists[index].next;
}
}
return result.next;
}
}
方法二
超时的原因可能是在于每次选最小值的时候,都需要便利一次数组,假设共有M行N列,最坏情况下最小的元素总是出现在最后一列,那么时间复杂度将达到
O(M∗NM)
所以考虑建立一个小根堆,建堆时堆中包括第一列的全部元素并排序,之后每抛出一个最小的,就将最小元素的后一个元素入堆,若不存在则跳过。这样时间复杂度可以降到
O(M∗NlogM)
就是编码麻烦一些,尝试一下。
最开始没有考虑数组中有空节点的情况,后来加了次筛选,将初始为空的节点移动到数组尾部。另外代码中用last变量代表数组中最后一个非空节点的下标。提交后果然AC,效率在前20%。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode result = new ListNode(0);
ListNode tail = result;
int last = lists.length - 1;
//将数组中的空节点移到尾部
for(int i = 0; i <= last;){
if (lists[i] == null){
lists[i] = lists[last];
lists[last] = null;
--last;
}else {
++i;
}
}
//第一次建堆
for(int i = (last-1)/2; i >= 0; --i){
createHeap(lists,i,last);
}
while(last >= 0){
tail.next = lists[0];
tail = tail.next;
if(lists[0].next != null){
lists[0] = lists[0].next;
}else{
lists[0] = lists[last];
lists[last] = null;
--last;
}
//每次都从根节点(下标为0)开始调整堆
createHeap(lists,0,last);
}
return result.next;
}
public void createHeap(ListNode[] lists,int target, int last){
ListNode temp;
int i = target;
int j = i * 2 + 1;
while(j >= 0 && j <= last){
if(j < last && lists[j].val > lists[j+1].val){
++j;
}
if(lists[j].val < lists[i].val){
temp = lists[j];
lists[j] = lists[i];
lists[i] = temp;
i = j;
j = i * 2 + 1;
}else{
break;
}
}
}
}