题目描述:
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
方法一:
- 比较 k 个节点(每个链表的首节点),获得最小值的节点。
- 将选中的节点接在最终有序链表的后面
- 选中节点往后走一步,继续上述过程
。
/**
* 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 min=Integer.MAX_VALUE;
int mark=-1;
for(int i=0;i<lists.length;i++){
if(lists[i]!=null&&lists[i].val<min){
min=lists[i].val;
mark=i;
}
}
if(mark==-1){
return null;
}
ListNode node=lists[mark];
lists[mark]=lists[mark].next;
node.next=mergeKLists(lists);
return node;
}
}
方法二:
将合并 k 个链表的问题转化成合并 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) {
int len=lists.length;
if(len==0){
return null;
}
while(len>1){
for(int i=0;i<len/2;i++){
lists[i]=mergeTwo(lists[i],lists[len-1-i]);
}
len=(len+1)/2;
}
return lists[0];
}
public ListNode mergeTwo(ListNode node1,ListNode node2){
ListNode head=new ListNode(0);
ListNode last=head;
while(node1!=null&&node2!=null){
if(node1.val<node2.val){
last.next=node1;
last=last.next;
node1=node1.next;
}else{
last.next=node2;
last=last.next;
node2=node2.next;
}
}
if(node1!=null){
last.next=node1;
}
if(node2!=null){
last.next=node2;
}
return head.next;
}
}
方法三:遍历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;
}
if(len==1){
return lists[0];
}
ListNode head=new ListNode(0);
ListNode cur=head;
if(len>1){
PriorityQueue<ListNode> q=new PriorityQueue<>(len,(n1,n2)->(n1.val-n2.val));
for(ListNode node:lists){
if(node!=null){
q.offer(node);
}
}
while(!q.isEmpty()){
ListNode acur=q.poll();
cur.next=acur;
cur=cur.next;
if(acur.next!=null){
q.offer(acur.next);
}
}
}
return head.next;
}
}