升序合并两个链表(链表本身已经升序排列,下同)
合并两个链表比较简单,需要注意的是要预先定义一个head,以及尽量代码写的简洁一些
public static ListNode merge2List(ListNode listNode1, ListNode listNode2) {
if (listNode1 == null) {
return listNode2;
} else if (listNode2 == null) {
return listNode1;
}
ListNode head = new ListNode();
ListNode tail = head;
ListNode a = listNode1;
ListNode b = listNode2;
while (a != null && b != null) {
if (a.val > b.val) {
tail.next = b;
b = b.next;
} else {
tail.next = a;
a = a.next;
}
tail = tail.next;
}
tail.next = (a != null ? a : b);
return head.next;
}
升序合并多个链表
合并多个链表可以在合并两个链表的基础上思考,最直接的想法就是将前两个链表合并,再把合并后的链表预第三个链表合并,以此类推。
在这个基础上做一些优化,可以想到用分治的思想,将链表集合分组,组内合并后再与其他组的合并结果进行合并。
public static ListNode mergeKLists2(ListNode[] lists) {
return merge(lists,0,lists.length-1);
}
public static ListNode merge(ListNode[] lists, int left, int right) {
if (left == right) {
return lists[left];
}
if (left > right) {
return null;
}
int mid = (left + right) >> 1;
return merge2List(merge(lists, left, mid), merge(lists, mid + 1, right));
}
此外看LeetCode题解的时候还了解到了新的思路,基于优先级的合并。
具体逻辑是将所有链表还没有被合并的第一个节点放入优先级队列,依靠优先级队列的特性取出最小的节点。
public static ListNode mergeKLists(ListNode[] lists) {
ListNode head = new ListNode();
if(lists.length==0){
return head;
}
PriorityQueue<ListNode> maxheap = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val-o2.val;
}
});
for (ListNode listNode : lists){
if(listNode!=null){
maxheap.offer(listNode);
}
}
ListNode next = null;
while (maxheap.size()>0){
ListNode min = maxheap.poll();
if(min.next!=null){
maxheap.offer(min.next);
}
if(next == null){
next = min;
head.next = next;
}else {
next.next = min;
next = next.next;
}
}
return head.next;
}