嗨小伙伴们好久不见,最近做题了吗??
今天我又发现了一道挺有意思的题,一起来看看吧!~
题目描述
首先看到的是亮眼的红色“困难”俩字,是什么样的题目竟然能够达到困难的难度?
难道它很难吗?不!不就是链表嘛,链表的问题能难到哪里去呢?(表面镇定,内心紧张)
虽然题目上来就标了困难的难度,但是咱们不慌,相信看完解答你就知道这道题其实一点都不难!废话不多说,先点个一键三连活动下手指,咱们立即开始今天的题解之路!~
复述题目:
有一个链表数组,数组中的每个链表都已经排好序了,现在让你把链表数组中是所有链表都合并到一起,返回合并后的链表。
下面看看给出的示例:
第一个示例,和题目意思一样。
示例2说明数组的大小可能为0。
示例3说明,数组中的链表可能为空链表。
然后我们再看看给出的代码:
右侧代码区只需要提交核心代码,给出了链表节点的结构,是我们熟悉的ListNode。方法返回值也是ListNode,说明我们需要将合并后的链表的头结点返回。
提示和示例中给出的差不多,数组的长度可能为0,链表的长度也可能为0,顺序是升序。
思路分析
看完了前面给出的描述和提示,首先想到的第一个思路应该是两两合并。
思路1:将前面两个链表合并,然后再将合并的链表与下一个链表合并,直到全部合并。
但是这样的做法未免太过低效,有没有高效一点的方法呢??
有也是有的,那就是分治。
思路2:分而治之
将数组中的链表两两分组,分别合并之后,链表数量减半,再次两两分分组,分别合并,直到最后合并成一个链表。
上面这两个做法的都建立在对两个升序链表进行合并的基础上,所以我们首先我们得会对两个升序链表进行合并。即写一个合并两个链表的方法。
那有没有不用对两个链表进行合并的方法呢?
当然有。
把每个链表的节点都放到一起比较,取最小的那个作为合并链表的下一个节点,然后再将当前最小链表的下一个节点加入比较的行列里。
其实这与将两个链表合并的本质逻辑仍然是一样的,不一样的是我们可以通过一个优先级队列来完成这个事情。
思路3:即用一个小堆进行排序,这样只要将每个链表的当前头结点扔到堆中,这样堆就会给我们直接给我们排出一个最小的节点,我们只需要对结果进行连接就可以了。
下面我们先从较为简单的开始!
思路3 解法
思路3底层需要我们会链表的尾插法:就是给你一个节点,你要一个一个地把它连在后面。为了方便,我们使用一个傀儡头结点head来作为链表的头部,这样后面拿到的节点只要连接到head后面就可以了。
上代码:
Java:
public ListNode mergeKLists1(ListNode[] lists) {
PriorityQueue<ListNode> queue = new PriorityQueue<>(new Comparator<ListNode>() {
@Override//这里注意要使用comparator告诉queue节点之间的比较方法
public int compare(