23. 合并K个排序链表
难度:困难
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
解法一:暴力法
创建一个数组,把所有链表的结点的val放进去,然后排序,再重组新的链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode result = new ListNode(0);
List<Integer> aList = new ArrayList<Integer>();
ListNode temp = result;
for(int i = 0;i<lists.length;i++) {
while(lists[i]!=null) {
aList.add(lists[i].val);
lists[i] = lists[i].next;
}
}
Collections.sort(aList);
for (Integer integer : aList) {
ListNode node = new ListNode(integer);
temp.next = node;
temp = temp.next;
}
return result.next;
}
}
解法二:优化队列+一次遍历
我们可以创建一个优化队列,首先把所有链表的头结点放入,然后每次拿出队列中最小的结点(即队首元素),让该结点出队,加入结果链表,并判断该结点是否还有next结点,若有,则把next结点继续入队,这样直到队列为空,就会得到结果链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode result = new ListNode(0);
ListNode temp = result;
PriorityQueue<ListNode> queue = new PriorityQueue<>(new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val-o2.val;
}
});
for(ListNode node:lists ) {
if(node!=null) {
queue.add(node);
}
}
while(!queue.isEmpty()) {
ListNode node = queue.poll();
temp.next = node;
temp = temp.next;
if(node.next!=null) {
queue.add(node.next);
}
}
return result.next;
}
}
解法三:分治法
我们可以把 k个链表分解为 k/2 组 两个链表的合并,然后再把 合并后的 k/2 个链表看成是 k/4 组两个链表的合并,然后 k/8,k/16……
直到最后合并成一个链表。
两个链表的合并可以参照我们之前的 21.合并两个有序链表 的解法。
代码:
/**
* 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;
}
return divideRule(lists, 0, lists.length - 1);
}
public ListNode divideRule(ListNode[] lists, int l, int r) {
if (l == r) {
return lists[l];
}
int mid = l + (r - l) / 2;
ListNode l1 = divideRule(lists, l, mid);
ListNode r1 = divideRule(lists, mid + 1, r);
return mergeTwoLists(l1, r1);
}
// 合并两个有序链表
public ListNode mergeTwoLists(ListNode a, ListNode b) {
if (a == null || b == null) {
return (a == null) ? b : a;
}
if (a.val <= b.val) {
a.next = mergeTwoLists(a.next, b);
return a;
} else {
b.next = mergeTwoLists(a, b.next);
return b;
}
}
}
网友评论