链表——leetcode23 合并K个升序链表

一、题目

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

二、思路

可以用小顶堆解答

小顶堆知识点
https://mp.weixin.qq.com/s/o7tdyLiYm668dpUWd-x7Lg

1.二叉堆概览

https://blog.csdn.net/u010224394/article/details/8834969
二叉堆是完全二叉树或者近似完全二叉树
二叉堆多数是以数组作为它们底层元素的存储,根节点在数组中的索引是1,存储在第n个位置的父节点它的子节点在数组中的存储位置为2n与2n+1,结果如下图所示

        1               
      /   \           
     2     3             
    / \   / \       
   4   5  6  7     
  / \ / \        
 8  9 10 11

满二叉树
满二叉树,除最后一层无任何子节点外,每一层上的所有结点都有两个子结点二叉树,如下所示

        1               
      /   \           
     2     3             
    / \   / \       
   4   5  6  7     

完全二叉树
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
通俗理解就是,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。

2.二叉堆分类

二叉堆分为最大堆和最小堆。
最大堆的性质是:每个节点都大于等于它的两个子节点。
最小堆的性质是:每个节点都小于等于它的子节点。

3.二叉堆的定义

https://blog.csdn.net/weixin_43207025/article/details/117754741?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242
https://www.liaoxuefeng.com/wiki/1252599548343744/1265120632401152#0
最小堆

PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //不指定Comparator时默认为小顶堆(最小堆),默认容量为11

最大堆

PriorityQueue<Integer> heap = new PriorityQueue<>(
                (w1, w2) -> w2 - w1    // 第二个参数减第一个是大顶堆
        );
上面的构造函数等同于下面
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
    @Override
    public int compare(Integer i1,Integer i2){
        return i2-i1;    //大顶堆执行poll()去掉的是大数,留下的是小数。构造方法传入(w1, w2) -> w2 - w1 // 第二个参数减第一个是大顶堆
    }
});

4.二叉堆方法

https://www.cnblogs.com/lingq/p/12735318.html
PriorityQueue的常用方法有:poll(),offer(Object),size(),peek()等。

插入方法(offer()、poll()、remove() 、add() 方法)时间复杂度为O(log(n)) ;
  remove(Object) 和 contains(Object) 时间复杂度为O(n);
  检索方法(peek、element 和 size)时间复杂度为常量。
  在这里插入图片描述

三、实现代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */

class Solution{
    ListNode mergeKLists (ListNode[] lists){
        //异常情况
        if (lists.length == 0) return null;
        //定义最后存放数据的链表
        ListNode result = new ListNode(-1);   //虚拟头结点
        ListNode p = result;
        //定义小顶堆
        PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length,(a,b)->(a.val-b.val));
        //把k个链表的head放到小顶堆中
        for (ListNode head:lists){
            if(head!=null){
                pq.add(head);
            }
        }
        //逐个找k个结点的下一个节点,并存入链表
        while (!pq.isEmpty()){
            ListNode node = pq.poll();
            p.next = node;
            if (node.next !=null){
                pq.add(node.next);
            }
            p = p.next;
        }
        return result.next;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值