首页 > 其他分享 >【LeetCode】23. 合并K个升序链表

【LeetCode】23. 合并K个升序链表

时间:2024-01-02 10:37:59浏览次数:33  
标签:ListNode lists next 链表 升序 moveNode LeetCode

一、题目描述

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

示例 3:

输入:lists = [[]]
输出:[]

提示:

  • k == lists.length
  • 0 <= k <= 10^4
  • 0 <= lists[i].length <= 500
  • -10^4 <= lists[i][j] <= 10^4
  • lists[i] 按 升序 排列
  • lists[i].length 的总和不超过 10^4

二、思路分析

首先从题目信息我们可以获取两个信息:

  1. 这里有多个链表,链表数量不是固定的
  2. 每个链表里的节点都是有序的,而且是升序

然后我们可以发现,想要合并所有的链表,每个链表有一个指针,每次比较获取所有链表中最小的那个节点,添加到新链表中,然后把原链表中的指针往后移一位,接着开始下一轮的比较……重复上述操作,直到所有链表的元素都添加到新链表中……

这里有一个重点,就是如何获取这些链表的最小节点?

最简单暴力的方法就是比较所有的指针指向节点获取最小值,但是循环比较是一个很费时间的操作,如果这样操作的话可能会超时。

那么是不是还有更加优雅的操作呢?

这时候就要考虑能不能缓存每次比较的结果,每次能在缓存的基础上获取最小值呢?这个肯定是有的,就是数据结构中的堆,我们可以使用小顶堆获取每轮比较的最小节点。

堆在Java中有可以直接使用的封装类——优先队列,我们可以实现一下比较方法,然后决定这是小顶堆,还是大顶堆。

代码实现

class Solution {
  // 实现比较器,通过节点的值做比较
    static Comparator<ListNode> comparator = new Comparator<ListNode>() {
        public int compare(ListNode e1, ListNode e2) {
            return e1.val - e2.val;
        }
    };

    public ListNode mergeKLists(ListNode[] lists) {
      // 实现小顶堆
        PriorityQueue<ListNode> queue = new PriorityQueue<>(comparator);
        ListNode ans = new ListNode();
        ListNode moveNode = ans;
        
        // 把非空的链表头节点添加到优先队列
        for (ListNode list : lists) {
            if (list != null) {
                queue.offer(list);
            }
        }
      // 队列不为空的时候继续比较
        while (!queue.isEmpty()) {
            moveNode.next = queue.poll();
            if (moveNode.next.next != null) {
                queue.offer(moveNode.next.next);
            }
            moveNode = moveNode.next;
        }
        return ans.next;
    }
}

总结

  1. 这种题主要是考察了数据结构中一些常用数据结构的性质,平时要多加熟悉,才能更好的运用在实际中。
  2. 一般遇到一堆无序数据中的最大值,最小值,第K大的值,可以优先考虑一下堆。

标签:ListNode,lists,next,链表,升序,moveNode,LeetCode
From: https://blog.51cto.com/u_15812995/9063842

相关文章

  • #yyds干货盘点# LeetCode程序员面试金典:赎金信
    给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次。 示例1:输入:ransomNote="a",magazine="b"输出:false示例2:输入:ransomNot......
  • #yyds干货盘点# LeetCode程序员面试金典:按权重随机选择
    题目给你一个下标从0开始的正整数数组w,其中w[i]代表第i个下标的权重。请你实现一个函数pickIndex,它可以随机地从范围[0,w.length-1]内(含0和w.length-1)选出并返回一个下标。选取下标i的概率为w[i]/sum(w)。例如,对于w=[1,3],挑选下标0的概率......
  • 代码随想录 小结02 链表
    第一题移除链表元素这题比较简单使用dummyHead的方式会比较简单不需要对头指针进行单独处理但是空间开销会大一些第二题设计链表类这个没什么好说的感觉有可能一些细节会忘记需要经常复习的一块第三题反转链表这题难度不大用一个tmp指针存储一下当前指针的next......
  • leetcode 2.两数相加
    leetcode第二题:两数相加以链表为载体模仿加法进位,同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个0。如果链表遍历结束后,有carry>0,还需要在答案链表的后面附加一个节点,节点的值为carry。易错点:1.......
  • 链表相交问题
    链表链表相交问题思路来源一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到笔记内容问题描述:现有两个单向链表,需要判断两个链表是否相交,若相交,返回链表最开始的交点,若不相交,则返回null算法思路:首先需要判断两个链表是否是环形链表,并获取环形链......
  • day03 代码随想录算法训练营 203. 移除链表元素
    题目:203.移除链表元素我的感悟:题目里的节点是已经给好的,创建虚拟节点,是为了方便处理头节点。加油,我可以的!!!!!理解难点:节点已经给好的创建虚拟节点代码难点:p是临时变量,类似于foriinrange(10)这里的i,本身是用完就扔的。返回值为什么不能是p.next?因为p是一个指针,......
  • 环形链表问题
    链表环形链表问题思路来源一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到笔记内容问题来源:基于力扣141题进行拓展问题描述:给你一个链表的头节点head,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存......
  • 【数据结构】链式家族的成员——循环链表与静态链表
    循环链表与静态链表导言大家好!很高兴又和大家见面啦!!!经过前面的介绍,相信大家对链式家族的成员——单链表与双链表的相关内容都已经熟练掌握了。前面我们重点介绍了通过C语言来实现单链表与双链表的一些基本操作,希望大家私下能够多多练习一下,帮助自己去吸收消化这些内容。在今天的篇......
  • 代码随想录day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表
    两两交换链表中的节点题目:这题画一下链表会比较清晰写写画画指针位置很快就可以写出来一开始以为一个tmp就够用了写着写着发现需要多一个代码:删除链表的倒数第N个节点:没什么思路只好先看看视频思路视频思路很简单也很清晰只需要两个指针一快一慢两指针的间......
  • leetcode 1.两数之和
    leetcode第一题:两数之和1.暴力枚举:最容易想到的方法是枚举数组中的每一个数x,寻找数组中是否存在target-x。当我们使用遍历整个数组的方式寻找target-x时,需要注意到每一个位于x之前的元素都已经和x匹配过,因此不需要再进行匹配。而每一个元素不能被使用两次,所以我们......