leetcode_23:合并K个排序链表

一、暴力法

暴力法不用做太多解释,代码也不写了,主要是两个暴力法:

  1. 每次都合并两个链表到一个上面,再用这个新链表继续和另一个链表进行合并。这样需要合并n-1次。
  2. 逐一比较的方法,就是每次从这K个链表的头结点中选一个最小的,然后加到新建的链表中,重复下去。

二、优先级队列(小顶堆)

其实就是上面暴力法2的一个变种,我们如何从K个链表的头结点中选一个最小的。方法就是建立一个小顶堆,然后每次从堆顶就可以取一个最小值。删掉堆顶元素后,查看删除的元素是否还有后继结点,有则加入到小顶堆中。代码如下:

public ListNode mergeKLists(ListNode[] lists) {
        if (lists.length == 0)
            return null;
        if (lists.length == 1)
            return  lists[0];
        //一定要注意新建优先级队列时候,初始化要用的参数
        //一个是堆的大小,一个是自定义的比较器    
        PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
            @Override
            public int compare(ListNode o1, ListNode o2) {
                if (o1.val < o2.val)
                    return -1;
                else if (o1.val > o2.val)
                    return 1;
                else
                    return 0;
            }
        });
        //将所有不为null的队列头放到堆中
        for (ListNode node : lists) {
            if (node != null)
                queue.offer(node);
        }
        ListNode result = new ListNode(-1), p = result;
        while (!queue.isEmpty()) { //堆不为空时,不断地取堆顶
            ListNode popNode = queue.poll();
            p.next = popNode; //将堆顶数据(当前最小的)放到结果后面
            p = p.next;
            if (popNode.next != null) { //堆顶还有后继,则把后继加入到堆中
                queue.offer(popNode.next);
            }
        }
        return result.next;

三、归并合并

就是每次都合并两个链表,两两合并。

public ListNode mergeKLists(ListNode[] lists) {
        if (lists.length == 0)
            return null;
        if (lists.length == 1)
            return  lists[0];
        int step = 1, index = 0;
        //很重要的一步,就是要知道index和step的条件
        while (index + step < lists.length) {
            for (; index+step < lists.length; index += 2*step) {
            	//将index和index+step位置的两个链表合并
                lists[index] = merge2Lists(lists[index], lists[index+step]);
            }
            index = 0;  //合并一次后,下标从0开始,step乘2
            step *= 2;
        }
        return lists[0];
    }

	//合并两个有序列表的过程
    public ListNode merge2Lists(ListNode list1, ListNode list2) {
        ListNode NewHead = new ListNode(0), head = NewHead;
        ListNode p1 = list1, p2 = list2;
        while (p1 != null && p2 != null) {
            if (p1.val <= p2.val) {
                head.next = p1;
                head = head.next;
                p1 = p1.next;
            } else {
                head.next = p2;
                head = head.next;
                p2 = p2.next;
            }
        }
        if (p1 != null) {
        	head.next = p1;
        }
        if (p2 != null) {
        	head.next = p2;
        }
        return NewHead.next;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值