LeetCode 23. Merge k Sorted Lists
2020-06-03 20:29:34 # leetcode # core problems

Problem

LeetCode 23. Merge k Sorted Lists

1. 题目简述

合并多个有序链表。例如:

Example:

Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6

2. 算法思路

极其经典的老题目,类似题目:LeetCode 21. Merge Two Sorted Lists

我们首先需要注意的是k个数组的话如果继续使用迭代的方式,会产生很多条件的判断,例如每次添加了一个节点之后,需要判断k个List中哪些已经到头了,计算起来很麻烦,而且易错。那么我们如何将问题分解成之前做过的“Merge 2 Sorted Arrays”呢?答案就是分治法。

分治法

每次二分整个lists,直到分为了两个list的合并或者一个单独的list,合并它们并返回。

时间复杂度:O(n * logk),n是所有list节点总数,k是list个数。这是因为我们其实一共需要对每个元素合并logk次,每次返回上一级都要重新合并,因此是乘法。

空间复杂度:O(logk),大部分的操作都是O(1)空间的,只有递归层数是需要压栈要空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) {
return null;
}
if (lists.length == 1) {
return lists[0];
}

return mergeLists(lists, 0, lists.length - 1);

}

// This function is used to divide numerous lists into smaller parts and merge them into one list.
private ListNode mergeLists(ListNode[] lists, int start, int end) {
if (start == end) {
return lists[start];
} else if (start == end - 1) {
return mergeTwoLists(lists[start], lists[end]);
} else {
int mid = start + (end - start) / 2;

ListNode left = mergeLists(lists, start, mid);
ListNode right = mergeLists(lists, mid + 1, end);

return mergeTwoLists(left, right);
}
}

private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode head = new ListNode(0);
ListNode ptr = head;

while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
ptr.next = l1;
ptr = ptr.next;
l1 = l1.next;
} else {
ptr.next = l2;
ptr = ptr.next;
l2 = l2.next;
}
}

ptr.next = l1 == null ? l2 : l1;

return head.next;
}
}