题目:
合并k个排序链表,并且返回合并后的排序链表。
样例
给出3个排序链表[2->4->null,null,-1->null],返回 -1->2->4->null
分析:
方法一:采用归并排序的思想。数组的数递归划分,一分二,二分四…直至最后一个数单独的成为一组,然后再进行归并划分采用的递归实现。即把K个链表一直对分直到最后一个链表为一组,然后进行递归两两归并,两两归并的操作即成了合并两个排序链表的题。
/**
* Definition for ListNode.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int val) {
* this.val = val;
* this.next = null;
* }
* }
*/
public class Solution {
/**
* @param lists: a list of ListNode
* @return: The head of one sorted list.
*/
public ListNode mergeKLists(List<ListNode> lists) {
// write your code here
if(lists==null ||lists.size()==0) return null;
return MSort(lists,0,lists.size()-1);
}
public ListNode MSort(List<ListNode> lists,int low,int high){
if(low==high)
return lists.get(low);
int mid=(low+high)/2;
ListNode leftlist=MSort(lists,low,mid);
ListNode rightlist=MSort(lists,mid+1,high);
return Merge(leftlist,rightlist);
}
public ListNode Merge(ListNode l1,ListNode l2){
if(l1==null) return l2;
if(l2==null) return l1;
ListNode l3;
if(l1.val<l2.val){
l3=l1;
l1=l1.next;
}else{
l3=l2;
l2=l2.next;
}
ListNode fakeHead=new ListNode(-1); //创建辅助头结点
fakeHead.next=l3;
while(l1!=null&&l2!=null){
if(l1.val<l2.val){
l3.next=l1;
l1=l1.next;
l3=l3.next;
}else{
l3.next=l2;
l2=l2.next;
l3=l3.next;
}
}
if(l1==null){
l3.next=l2;
}
if(l2==null){
l3.next=l1;
}
return fakeHead.next;
}
}
方法二:
使用堆排序(小根堆),把所有头结点放入堆中,每次取出根结点,放到新建头结点的下一个结点,并把取出来的结点的下一个结点放入堆中,直到堆中没有结点。
public ListNode mergeKLists1(List<ListNode> lists) {
if(lists.size()==0||lists==null) return null;
Queue<ListNode> heap=new PriorityQueue<>(lists.size(), new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val-o2.val;
}
});
//把头结点放入堆中
for(int i=0;i<lists.size();i++){
if(lists.get(i)!=null)
heap.add(lists.get(i));
}
//新建头结点
ListNode dummy=new ListNode(-1);
//每次把堆中的根结点取出,接到头结点之后
ListNode cur=dummy;
while(heap.size()>0){
ListNode head=heap.poll();
cur.next=head;
cur=head;
if(head.next!=null){
heap.add(head.next);
}
}
return dummy.next;
}