leetcode 23 : 合并K个升序链表

157 阅读2分钟

题目 leetcode23-合并K个升序链表


  • 难度:hard;
  • 字节半年出现:23 次;

思路

  • 用 java 的优先级队列 PriorityQueue 维持一个小根堆 (不是非得用二叉树)
  • 穿针引线(循环),不断的链接小根堆上最小的节点
  • 看下图,谢一姐 她是我刷题的路的灯....

leet_code-23.png

基础 与联想

  1. 基础知识:leetCode-21 合并两个有序链表
  2. java 的优先级队列 PriorityQueue
  3. 想想自己是不是刷过 leetcode 253 会议室

代码

 /**
     * 一姐的思路,我的注释
     * @param lists
     * @return
     */
    public ListNode mergeKLists(ListNode[] lists) {
        // 优先级队列, 用 ListNode[] 数组中,每个链表的头结点的 val 做比较;
        // 小的放前面,大的放后面 (是不是有点像冒泡排序?)
        PriorityQueue<ListNode> minHeap = new PriorityQueue<>((a, b) -> a.val - b.val);
        // 将 数组参数lists 中的几点,全部放入优先级队列中 PriorityQueue
        for (ListNode list : lists) {
            // 当心测试 case 里面,放一个null 链表,
            // 编程经验:不要相信别人传过来的参数,一定要做非法校验,
            // 人家调一些非法参数,你的函数蹦了,那就你的问题;
            // 而不是别人的问题。没办法,行走江湖,就是这么的残酷
            if (list == null) {
                continue;
            }
            // 放.....
            minHeap.add(list);
        }

        // dummy 大法(不解释...我也不会解释...没空,,我要刷题,,,)
        ListNode dummy = new ListNode(-1);
        ListNode curr = dummy;
        //
        while (minHeap.size() != 0) {
            // 1: 获取最小节点,不用怀疑,PripoQueue 队列 第 0 的位置已近是最小的节点了;
            ListNode minNode = minHeap.remove();
            // 2:将最小节点连接到 curr 的下一节点上(心里默念:穿针引线...)
            curr.next = minNode;
            // 3:当前节点后移一位(ps: 就是往前走一步)
            curr = curr.next;
            // 想一下,为啥可能为空的? 回头看第2步,curr 的 next 节点,是不是连接了 minNode 节点啊?
            // minNode 是不是 会有下一个节点啊?为啥?我操?
            // think again :minNode节点元素,最原始的数据,是不是 通过 for 循环遍历lists 数组放进去的啊?
            // 这下,明白了吧
            if (curr.next != null) {
                //  minNode 当点节点已经被 curr 的 next 节点连接上了,
                // minHeap后面的节点还没有被使用,所有要将minHeap的下一个节点放到优先级队列中,
                // 优先级队列会在内部对他们进行排列的(小泡泡放已经被放在队列的第 0 个位置了...不行自己 debug)
                minHeap.add(minNode.next);
            }
        }
        // 用 dummy 大法返回结果;
        return dummy.next;

    }