题目描述
合并 k 个已排序的链表并将其作为一个已排序的链表返回。分析并描述其复杂度。
[{1,2,3},{4,5,6,7}]
{1,2,3,4,5,6,7}
解决方法一:
遍历链表数组,两两合并链表。其中合并两个有序链表也是一个算法题,点击此处查看。
import java.util.*;
/**
* 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(ArrayList<ListNode> lists) {
if (lists.size() == 0) return null;
if (lists.size() == 1) return lists.get(0);
ListNode res = lists.get(0);
for (int i = 1; i < lists.size(); i++) {
res = mergeTwoLists(res, lists.get(i));
}
return res;
}
public ListNode mergeTwoLists(ListNode head1, ListNode head2) {
if (head1 == null) return head2;
if (head2 == null) return head1;
if (head1.val < head2.val) {
head1.next = mergeTwoLists(head1.next, head2);
return head1;
} else {
head2.next = mergeTwoLists(head2.next, head1);
return head2;
}
}
}
解决方法二
使用优先队列
,其本质也就是大小堆
。以每个链表头节点大小为标准,小的优先放入队列。
然后,由于cur
是逐个节点遍历的,每次cur.next
都被赋值为当前队列中队首元素最小的节点(也就是每次都会找到剩余链表中最小节点连接到cur
后面)。于此同时,还需要将每一步寻找到最小节点的所在的链表的剩余节点,添加到队列中。
import java.util.*;
/**
* 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(ArrayList<ListNode> lists) {
if (lists == null || lists.size() == 0) return null;
PriorityQueue<ListNode> queue = new PriorityQueue<ListNode>(lists.size(), new Comparator<ListNode>(){
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val < o2.val ? -1 : 1;
}
});
for (ListNode node : lists) {
if (node != null){
queue.add(node);
}
}
ListNode res = new ListNode(-1);
ListNode cur = res;
while (! queue.isEmpty()) {
cur.next = queue.poll();
cur = cur.next;
if (cur.next != null) {
queue.add(cur.next);
}
}
return res.next;
}
}