合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
首先想到的是暴力解法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int len = lists.length;
if(len==0) return null;
List<Integer> list = new ArrayList<>();
for(int i=0;i<len;i++){
ListNode node = lists[i];
while(node!=null){
list.add(node.val);
node=node.next;
}
}
int size = list.size();
if(size==0) return null;
ListNode res = new ListNode();
ListNode temNode = res;
Collections.sort(list);
for(int i=0;i<size;i++){
temNode.val=list.get(i);
if(i<size-1){
temNode.next = new ListNode();
temNode=temNode.next;
}
}
return res;
}
}
再有就是之前好像做过两个有序链表的合并,所以就有了第二个方法,顺序合并
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int len = lists.length;
if(len==0) return null;
ListNode res = lists[0];
for(int i=1;i<len;i++){
res = mergeTowListNode(res,lists[i]);
}
return res;
}
//两个有序链表合并
private ListNode mergeTowListNode(ListNode node1,ListNode node2){
ListNode res = new ListNode(0);
ListNode temp = res;
while(node1!=null||node2!=null){
if(node1==null){
temp.next=node2;
return res.next;
}
if(node2==null){
temp.next = node1;
return res.next;
}
if(node1.val<=node2.val){
temp.next=node1;
node1=node1.next;
}else{
temp.next=node2;
node2 = node2.next;
}
temp=temp.next;
}
return res.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) {
int len=lists.length;
return merge(lists,0,len-1);
}
private ListNode merge(ListNode[] lists,int left,int right){
if(left==right) return lists[left];
if(left>right) return null;
int mid = left+(right-left)/2;
return mergeTowListNode(merge(lists,left,mid),merge(lists,mid+1,right));
}
//合并两个有序链表
private ListNode mergeTowListNode(ListNode l1,ListNode l2){
ListNode res = new ListNode(0);
ListNode head = res;
while(l1!=null&&l2!=null){
if(l1.val<=l2.val){
head.next=l1;
l1=l1.next;
}else{
head.next=l2;
l2=l2.next;
}
head=head.next;
}
if(l1==null) {
head.next=l2;
}else{
head.next=l1;
}
return res.next;
}
}
还有一个方法是使用优先队列(PriorityQueue),具体请看代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
//定义有序队列
PriorityQueue<ListNode> minHead = new PriorityQueue<>((ListNode l1,ListNode l2)->Integer.compare(l1.val,l2.val));
for(ListNode l:lists){
if(l!=null) minHead.add(l);
}
ListNode res = new ListNode(0);
ListNode temp = res;
while(!minHead.isEmpty()){
ListNode cur = minHead.poll();
temp.next=cur;
temp = temp.next;
if(cur.next!=null) minHead.add(cur.next);
}
return res.next;
}
}
以上方法除方法以外都参考了官方的题解