[杨小白]_leetcode_23. 合并K个升序链表

75 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标300题,记录从0到1的全过程!!

23. 合并K个升序链表

23. 合并K个升序链表

这是一道困难的链表题,但是也算是一道很常见,也需要学会的hard题,他算是leetcode主站21题, 21. 合并两个有序链表。和剑指offer25题, 剑指 Offer 25. 合并两个排序的链表的一个变种题目把。

做链表题目必须要先做过这两个题,才算是对链表有了基本的了解。

现在介绍这个题。

题目

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

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

示例 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

2.解法

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue<ListNode> queue = new PriorityQueue<>((o1,o2) -> o1.val - o2.val);
        for(int i = 0; i < lists.length; i++) {
            if(lists[i]!=null)
            queue.offer(lists[i]);
        }
        ListNode res = new ListNode(0);
        ListNode cur = res;
        while(queue.size()>0) {
            ListNode node = queue.poll();
            cur.next = node;
            node = node.next;
            if(node!=null)
                {queue.offer(node);}
            cur = cur.next;
        }
        cur.next = queue.poll();
        return res.next;
    }
}

提交排名

image.png

解析

这个题起初拿到手,思考很久不知道怎么做,每次遍历各个头节点找到最小的那一个然后添加到返回ListNode的列表中吗?不仅实现复杂,而且复杂度也高。每次都要遍历,又有这么多的节点数,那时间复杂度有O(n*m)

所以想到可以运用java自带的集合类型PriorityQueue(),让优先级队列按照每个节点的val进行降序排列,每次拿出最后一个最小的节点即可。

每次拿出最小的节点Node,将Node加入返回值的链表中,然后将Node.next重新添加进PriorityQueue,直到Node.next为空的时候,就不再添加,这样当PriorityQueue中没有元素的时候,就已经排序成功了。

3.结束

这个题没做过还是难以想到的,如果做过之后,以后遇到也就不怕了,gogogo,刷题刷题,每天一道,三年1000道!!!!