#23 合并K个排序链表
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
思路
方法1:尾部合并法
- 从尾部开始合并,合并后的链表放在尾部,数组长度逻辑上减1。
- 使用一个size变量维护数组长度(模拟栈)。
- 参考 #21 合并两个有序链表
方法2:分治法
- 将k个链表配对并将同一对中的链表合并。
- 第一轮合并以后,k个链表被合并成了k/2个链表,然后是k/4个链表,k/8个链表等等。
- 重复这一过程,直到我们得到了最终的有序链表。
方法3:使用优先队列合并
- 找当前的k个链表的值最小的节点,然后依次将其插入结果链表。
代码
方法1
/**
* 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];
//size是待合并链表数量
int size = lists.length;
//合并两个链表,直到只剩下一条链表。
while(size > 1){
ListNode l1 = lists[size-2];
ListNode l2 = lists[size-1];
ListNode res = mergeTwoLists(l1,l2);
//数组长度逻辑减1
size--;
//将合并后的链表放在数组的逻辑尾部
lists[size-1] = res;
}
return lists[0];
}
//合并两个有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null) return l2;
if(l2 == null) return l1;
//选择头结点
ListNode result = new ListNode(0);
ListNode nn = result;
if(l1.val<l2.val){
result.next = l1;
l1 = l1.next;
}else{
result.next = l2;
l2 = l2.next;
}
result = result.next;
for(;l1 != null && l2 != null;){
if(l1.val<l2.val){
result.next = l1;
l1 = l1.next;
result = result.next;
}else{
result.next = l2;
l2 = l2.next;
result = result.next;
}
}
if(l1 == null){
result.next = l2;
result = result.next;
}else{
result.next = l1;
result = result.next;
}
return nn.next;
}
}
方法2
/**
* 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 meger(lists, 0, lists.length-1);
}
//递归合并链表数组
//l1会从最左侧开始合并,l2从最右侧开始合并。
public ListNode meger(ListNode[] lists, int left, int right){
if(left == right) return lists[left];
//将链表数组二分
int mid = left + (right-left)/2;
ListNode l1 = meger(lists,left,mid);
ListNode l2 = meger(lists,mid+1,right);
return mergeTwoLists(l1,l2);
}
//合并两条有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null) return l2;
if(l2 == null) return l1;
//选择头结点
ListNode result = new ListNode(0);
ListNode nn = result;
if(l1.val<l2.val){
result.next = l1;
l1 = l1.next;
}else{
result.next = l2;
l2 = l2.next;
}
result = result.next;
for(;l1 != null && l2 != null;){
if(l1.val<l2.val){
result.next = l1;
l1 = l1.next;
result = result.next;
}else{
result.next = l2;
l2 = l2.next;
result = result.next;
}
}
if(l1 == null){
result.next = l2;
result = result.next;
}else{
result.next = l1;
result = result.next;
}
return nn.next;
}
}
方法3
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
Queue<ListNode> pq = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);
for (ListNode node: lists) {
if (node != null) {
pq.offer(node);
}
}
ListNode dummyHead = new ListNode(0);
ListNode tail = dummyHead;
while (!pq.isEmpty()) {
ListNode minNode = pq.poll();
tail.next = minNode;
tail = minNode;
if (minNode.next != null) {
pq.offer(minNode.next);
}
}
return dummyHead.next;
}
}
/*
这个方法还不会,先抄一下大佬的代码。
作者:sweetiee
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/4-chong-fang-fa-xiang-jie-bi-xu-miao-dong-by-sweet/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/