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
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
Queue<ListNode> deque = new LinkedList<>();
for (ListNode node : lists) {
if (node != null) {
deque.offer(node);
}
}
while (deque.size() > 1) {
ListNode nodeOne = deque.poll();
ListNode nodeTwo = deque.poll();
deque.offer(merge(nodeOne, nodeTwo));
}
return deque.size() != 0 ? deque.poll() : null;
}

private ListNode merge(ListNode nodeOne, ListNode nodeTwo) {
ListNode prev = null, currNode = nodeOne, ptr = nodeTwo;
while (currNode != null && ptr != null) {
if (currNode.val <= ptr.val) {
prev = currNode;
currNode = currNode.next;
} else {
if (prev != null) {
prev.next = ptr;
}
prev = ptr;
ptr = ptr.next;
prev.next = currNode;
}
}
if (currNode == null) {
prev.next = ptr;
}
return nodeOne.val <= nodeTwo.val ? nodeOne : nodeTwo;
}
}

第一种解法就是两两合并. 我们用一个queue来装node. 每次从头部拿两个合并, 合并好的再放到尾部. 我之前想的是严格按照两两合并.比如开始有偶数个, 那可以两两合并, 合并完可能出现奇数个, 这样的话会剩下一个不能合并, 但是不让这个剩下的掺和到那些它前面两两合并好的list中. 但其实不用这么严格, 剩下的这个和后面那个之前合并好的合并不就行

时间复杂度: O(nlogk) n是node的总个数, k是lists的长度. 我们每内部循环走一遍就会遍历所有的nodes, 一共要合并logk次, 因此是Nlogk
空间复杂度: O(k)

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
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
Queue<ListNode> deque = new LinkedList<>();
for (ListNode node : lists) {
if (node != null) {
deque.offer(node);
}
}
while (deque.size() > 1) {
int size = deque.size();
int count = 0;
while (count < size) {
if (size - count > 1) {
ListNode nodeOne = deque.poll();
ListNode nodeTwo = deque.poll();
deque.offer(merge(nodeOne, nodeTwo));
count += 2;
} else {
deque.offer(deque.poll());
count += 1;
}
}
}
return deque.size() != 0 ? deque.poll() : null;
}

private ListNode merge(ListNode nodeOne, ListNode nodeTwo) {
ListNode prev = null, currNode = nodeOne, ptr = nodeTwo;
while (currNode != null && ptr != null) {
if (currNode.val <= ptr.val) {
prev = currNode;
currNode = currNode.next;
} else {
if (prev != null) {
prev.next = ptr;
}
prev = ptr;
ptr = ptr.next;
prev.next = currNode;
}
}
if (currNode == null) {
prev.next = ptr;
}
return nodeOne.val <= nodeTwo.val ? nodeOne : nodeTwo;
}
}

这个是严格一层一层的合并, 也就是两两合并, 剩下的一个就保留到下一次. 其实没必要.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> nodeQ = new PriorityQueue<>((a, b) -> a.val - b.val);
for (int i = 0; i < lists.length; i++) {
if (lists[i] != null) {
nodeQ.offer(lists[i]);
}
}
ListNode dummy = new ListNode(0), ptr = dummy;
while (!nodeQ.isEmpty()) {
ListNode currNode = nodeQ.poll();
ptr.next = currNode;
if (currNode.next != null) {
nodeQ.offer(currNode.next);
}
ptr = ptr.next;
}
return dummy.next;
}
}

这个是用priority queue. 为啥想到用PQ? 因为合并K arrays, 条件反射.
时间复杂度和空间复杂度不变.