Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
这道题要求归并k个排好序的lists。
解法1: 分治策略
凭借我们现在已有的知识,我们只知道如何归并两个排好序的list,在Merge Two Sorted Lists里面给出了很详细的过程,这里直接给出代码
public ListNode merge(ListNode l1, ListNode l2) {
ListNode helper = new ListNode(0);
ListNode runner = helper;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
runner.next = l1;
l1 = l1.next;
runner = runner.next;
} else {
runner.next = l2;
l2 = l2.next;
runner = runner.next;
}
if (l1 != null)
runner.next = l1;
if (l2 != null)
runner.next = l2;
}
return helper.next;
}
如何把merge k 变成 merge 2呢?
这里我们第一个想到的是分治策略。k-->k/2-->k/4-->k/8-->...-->2
代码如下:
public ListNode helper(ArrayList<ListNode> lists, int left, int right) {
if (left == right)
return lists.get(left);
int middle = (left + right) / 2;
return merge(helper(lists, left, middle),
helper(lists, middle + 1, right));
}
public ListNode mergeKLists(ArrayList<ListNode> lists) {
if (lists == null || lists.size() == 0)
return null;
return helper(lists, 0, lists.size() - 1);
}
public ListNode helper(ArrayList<ListNode> lists, int left, int right) {
if (left == right)
return lists.get(left);
int middle = (left + right) / 2;
return merge(helper(lists, left, middle),
helper(lists, middle + 1, right));
}
public ListNode merge(ListNode head1, ListNode head2) {
ListNode helper = new ListNode(0);
ListNode runner = helper;
while (head1 != null && head2 != null) {
if (head1.val < head2.val) {
runner.next = head1;
head1 = head1.next;
} else {
runner.next = head2;
head2 = head2.next;
}
runner = runner.next;
}
if (head1 != null)
runner.next = head1;
if (head2 != null)
runner.next = head2;
return helper.next;
}
解法2:堆排序
这道题还可以使用堆排序,思路是把所有的list的头个节点放进堆里面,然后依次弹出最小的节点尾插到新的链表中,并且更新头结点为下一个节点。这样就可以从小到大把所有节点都弹出来
首先是把所有头结点放入堆中
for (int i = 0; i < lists.size(); i++) {
ListNode node = lists.get(i);
if (node != null) {
heap.offer(node);
}
}
然后插入最小节点并更新已插入节点的头结点。
ListNode helper = new ListNode(0);
ListNode runner = helper;
while (heap.size() > 0) {
ListNode temp = heap.poll();
runner.next = temp;
runner = runner.next;
if (temp.next != null)
heap.offer(temp.next);
}
最后给出完整代码。
public ListNode mergeKLists(ArrayList<ListNode> lists) {
PriorityQueue<ListNode> heap = new PriorityQueue<ListNode>(1,
new Comparator<ListNode>() {
@Override
public int compare(ListNode n1, ListNode n2) {
return n1.val - n2.val;
}
});
for (int i = 0; i < lists.size(); i++) {
ListNode node = lists.get(i);
if (node != null) {
heap.offer(node);
}
}
ListNode helper = new ListNode(0);
ListNode runner = helper;
while (heap.size() > 0) {
ListNode temp = heap.poll();
runner.next = temp;
runner = runner.next;
if (temp.next != null)
heap.offer(temp.next);
}
return helper.next;
}