Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
这个题跟Merge 2 sorted linked lists相似,一开始采用合并两条链表的方法,顺序合并k个链表,发现会有一个k比较大的用例一直通不过,显示TimeOut。这个题看了下,属于hard,其实思路很简单,但归属于hard,我感觉就是需要考虑时间复杂度,如果不考虑时间复杂度,其实还是属于比较简单的。程序如下所示:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
private ListNode mergeTwoRow(ListNode l0, ListNode l1){
if (l0 == null||l1 == null){
return (l0 == null)?l1:l0;
}
ListNode head = new ListNode(0);
ListNode tmp = head;
while (l0 != null&&l1 != null){
if (l0.val <= l1.val){
tmp.next = l0;
l0 = l0.next;
}
else {
tmp.next = l1;
l1 = l1.next;
}
tmp = tmp.next;
}
tmp.next = (l0 == null)?l1:l0;
return head.next;
}
public ListNode mergeKLists(ListNode[] lists) {
ListNode head = new ListNode(0);
ListNode tmp = null;
for (int i = 0; i < lists.length; ++ i){
tmp = mergeTwoRow(tmp, lists[i]);
}
return tmp;
}
}
上面这种方式会出现大量的重复比对,最先排好序的元素会被扫描多次,原因就在于for循环是顺序执行,且每次都将整合好的链表与下一个有序链表进行整合,所以这个地方可以优化,很明显,这里可以用分治思想处理,程序如下所示:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
private ListNode mergeTwoRow(ListNode l0, ListNode l1){
if (l0 == null||l1 == null){
return (l0 == null)?l1:l0;
}
ListNode head = new ListNode(0);
ListNode tmp = head;
while (l0 != null&&l1 != null){
if (l0.val <= l1.val){
tmp.next = l0;
l0 = l0.next;
}
else {
tmp.next = l1;
l1 = l1.next;
}
tmp = tmp.next;
}
tmp.next = (l0 == null)?l1:l0;
return head.next;
}
public ListNode merge(ListNode[] lists, int begin, int end){
if (begin == end) {
return lists[begin];
}
if (begin < end){
int mid = (begin + end)/2;
ListNode l0 = merge(lists, begin, mid);
ListNode l1 = merge(lists, mid + 1, end);
return mergeTwoRow(l0, l1);
}
else {
return null;
}
}
public ListNode mergeKLists(ListNode[] lists) {
return merge(lists, 0, lists.length - 1);
}
}