Question
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
*Difficulty: Hard, Frequency: High
https://leetcode.com/problems/merge-k-sorted-lists/
My Solution
首先想到的是标准的divide and conquer的问题,两两Merge,到最后一共用klogk步就搞定了,time complexity O(nklogk), space O(1)
/**
* 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) {
if(lists.length == 0) return null;
if(lists.length == 1) return lists[0];
ArrayList<ListNode> listAry = new ArrayList<>(Arrays.asList(lists));
while(listAry.size() > 1){
for(int i = 0; i < listAry.size(); i++){
if(i+1 < listAry.size()){
ListNode mergedList = merge2Lists(listAry.get(i), listAry.get(i+1));
listAry.remove(i);
listAry.remove(i);
listAry.add(i, mergedList);
}
}
}
return listAry.get(0);
}
private ListNode merge2Lists(ListNode list1, ListNode list2){
ListNode head = new ListNode(0);
ListNode dummyHead = head;
while(list1 != null && list2 != null){
if(list1.val < list2.val){
head.next = list1;
list1 = list1.next;
}else{
head.next = list2;
list2 = list2.next;
}
head = head.next;
}
if(list1 != null) head.next = list1;
if(list2 != null) head.next = list2;
return dummyHead.next;
}
}
Other solutions
brute force, 不用说了,就是一个一个linked list慢慢merge下去吧,O(nk^2)的time complexity
另一种是用Heap也就是Priority queue,可以稍微快一点,算是用一个比较优化的data structure来做insert, O(nk log k) runtime, O(1) space, 但是本质的algo还是觉得divide and conquer要好一些
具体讲一下heap:
先弄一个Min的heap,把所有ListNodes都存进去Priority queue里面,每次用Poll()把head of the queue那个node拿出来,连到p上面(设为p.next),然后把这个node的next放回到Priorityqueue里面(queue会自动排好序),以此类推直到queue里没元素为止。*值得注意的是,因为ListNode本身没有comparator可以让priority queue用来sort,要override一下。
code:
private static final Comparator<ListNode> listComparator =
new Comparator<ListNode>() {
@Override
public int compare(ListNode x, ListNode y) {
return x.val - y.val;
}
};
public ListNode mergeKLists(List<ListNode> lists) {
if (lists.isEmpty()) return null;
Queue<ListNode> queue = new PriorityQueue<>(lists.size(), listComparator);
for (ListNode node : lists) {
if (node != null) {
queue.add(node);
}
}
ListNode dummyHead = new ListNode(0);
ListNode p = dummyHead;
while (!queue.isEmpty()) {
ListNode node = queue.poll();
p.next = node;
p = p.next;
if (node.next != null) {
queue.add(node.next);
}
}
return dummyHead.next;
}