思路1
由于是很多个链表合并,每次都要取出链表进行操作,想到偷懒的算法,使用优先队列来储存链表中的元素,优先队列会自动将链表中数的大小进行排序,之后新建链表来将优先队列中的元素串联起来即可,思路较为简单,代码如下:
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
ListNode node = new ListNode();
for(int i=0;i<lists.length;i++){
ListNode head = lists[i];
if(head==null) continue;
while (head.next!=null){
queue.offer(head.val);
head = head.next;
}
queue.offer(head.val);
}
ListNode result = node;
if(queue.isEmpty()) return null;
node.val = queue.poll();
while (!queue.isEmpty()){
ListNode nodeNext = new ListNode();
nodeNext.val = queue.poll();
node.next = nodeNext;
node = nodeNext;
}
return result;
}
}
思路2
采用分治的思想来处理,可以先合并两个链表,之后循环合并这两个链表即可,则思路可转变为合并两个升序链表。
1.首先定义一个链表
l
i
s
t
n
o
d
e
listnode
listnode表示合并之后的链表,
l
i
s
t
n
o
d
e
listnode
listnode链表不会变动,永远指向头节点。
2.再定义一个链表
t
a
i
l
tail
tail,该指针指向下一个要插入的链表节点。
3.此外,还有两个需要合并的链表,我将他们表示为
f
i
s
t
n
o
d
e
fistnode
fistnode和
s
e
c
o
n
d
n
o
t
e
secondnote
secondnote,以有序数组
[
1
,
4
,
5
]
[1,4,5]
[1,4,5]和有序数组
[
1
,
3
,
4
]
[1,3,4]
[1,3,4]为例。
则具体的步骤如下:
通过条件判断:若 f i r s t n o d e firstnode firstnode 的值小于 s e c o n d n o t e secondnote secondnote ,则 t a i l . n e x t tail.next tail.next 指向 f i r s t n o d e firstnode firstnode ,反之,则 t a i l . n e x t tail.next tail.next 指向 s e c o n d n o t e secondnote secondnote 。之后 f i r s t n o d e / s e c o n d n o t e firstnode/secondnote firstnode/secondnote 和 t a i l tail tail 同时跳到下个节点。
如图中所示,此时
t
a
i
l
tail
tail 指向
s
e
c
o
n
d
second
second,
s
e
c
o
n
d
second
second指向
s
e
c
o
n
d
.
n
e
x
t
second.next
second.next:
再次比较重复上述操作,此时 t a i l tail tail指向 f i r s t n o d e firstnode firstnode:
继续重复上述操作,可以得到一条合并之后的升序链表,即图中黄色实线所示:
则返回之前保存的 l i s t n o d e . n e x t listnode.next listnode.next 即为合并之后的升序列表,代码如下:
public ListNode merge(ListNode first,ListNode second){
ListNode listnode = new ListNode();
if(first == null) return second;
if(second == null) return first;
ListNode tail = listnode;
while (first!=null && second!=null){
if(first.val<second.val){
tail.next = first;
tail = tail.next;
first = first.next;
}else {
tail.next = second;
tail = tail.next;
second = second.next;
}
}
if(first == null) tail.next = second;
if(second == null) tail.next = first;
return listnode.next;
}
此即为合并两个有序链表的方法,通过不断重复调用可得到最终完整的有序链表,完整代码如下:
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length==0) return null;
ListNode listnode = null;
for(int i=0;i<lists.length;i++){
listnode = merge(listnode,lists[i]);
}
return listnode;
}
public ListNode merge(ListNode first,ListNode second){
ListNode listnode = new ListNode();
if(first == null) return second;
if(second == null) return first;
ListNode tail = listnode;
while (first!=null && second!=null){
if(first.val<second.val){
tail.next = first;
tail = tail.next;
first = first.next;
}else {
tail.next = second;
tail = tail.next;
second = second.next;
}
}
if(first == null) tail.next = second;
if(second == null) tail.next = first;
return listnode.next;
}
}