005-023-Merge k sorted lists 合并K个有序的链表

Description

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

分析

  归并多个排序的链表为一个有序链表。这是继merge two sorted list之后的一个扩展,早几天面试的时候面试官直接要我在电脑上OJ这题。

  对于两个已经排序的链表,我们知道最小值定在两个头节点,然后我们通过比较获得最小节点之后,移动指向最小节点的指针,那么下一个最小节点还是在两个头节点中。

image

  将k个已排序的链表归并为一个有序链表,关键就是在k个链表中找到最小的节点,然后移除该节点并将其插入到输出链表的尾部,继续查找下一个最小节点,直到k个链表都为空。那么如何寻找最小节点呢?k个链表都是为有序的链表,那么每个链表中的最小节点在链表的头节点,所有链表中的最小节点就在k个链表的头节点中找,当移除最小节点后,该链表会有一个新的头节点,最小值还是在k个链表的头节点中找。如此重复,直到k个链表都为空,我们就能得到一个排序的链表了。

  那么如何快速找到这个最小节点呢,寻找最小值,那用堆啊。建立一个初始大小为k的堆,将k个链表的头节点放入其中。接着从堆中取出最小节点,添加到输出链表尾部,再将该最小节点的下一个节点插入堆中,若下一个节点为空,则说明已经到达链表尾部,该链表已经无需再处理。重复上述过程,直至堆为空,k个有序链表就归并为一个有序链表了。

  数据结构采用PriorityQueue,为节点建立一个比较器。

  若节点总数为n,堆的大小为k,对堆的插入或取出操作需要O(logk),那么这个算法的时间复杂度为O(nlogk)。空间复杂度为O(k)。

Code

使用heap
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */

public class Solution {
    public class NodeCompare implements Comparator<ListNode>{
        public int compare(ListNode n1,ListNode n2){
            return n1.val-n2.val;
        }
    }
    public ListNode mergeKLists(ListNode[] lists) {
        int k=lists.length;//heap size
        ListNode tmpHead=new ListNode(-1);//fake head
        ListNode cur=tmpHead;//current pointer
        
        if(k==0)return tmpHead.next;
        if(k==1)return tmpHead.next=lists[0];
        else{
            PriorityQueue<ListNode> heap=new PriorityQueue<ListNode>(k,new NodeCompare());
            // k size heap, natrual order, aka min heap 
            
            //initialize heap, the min node is in the head of all list
            for(int i=0;i<k;i++){
                if(lists[i]!=null){
                    heap.offer(lists[i]);
                }
            }
            
            //find min till empty
            while(!heap.isEmpty()){
                ListNode min=heap.poll();//find min node
                cur.next=min;//append to the output list
                cur=cur.next;//cur move a step
                if(min.next!=null){//if this list is empty, move on
                    heap.offer(min.next);//insert next node
                }
                //continue 
            }
            
            return tmpHead.next;
        }
        
        
    }
}

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值