• 23 合并K个升序链表(LeetCode HOT 100)


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

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

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

    Soulution(暴力解法-直接上堆排序):

        /**
         * 合并K个链表(堆排序)
         *
         * @param lists 列表
         * @return {@link ListNode}
         */
        public static ListNode mergeKLists(ListNode[] lists) {
    
            // 构造优先队列
            PriorityQueue<ListNode> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(o -> o.val));
            for (ListNode list : lists) {
                while (list != null) {
                    priorityQueue.add(list);
                    list = list.next;
                }
            }
    
            // 结果集
            ListNode sentry = new ListNode();
            ListNode point = sentry;
    
            while (!priorityQueue.isEmpty()) {
                point.next = priorityQueue.poll();
                // 避免出现cycle
                point.next.next = null;
                point = point.next;
            }
    
            return sentry.next;
        }
    

    Soulution(分而治之):

    /**
         * 合并K个链表(分治思想)
         *
         * @param lists 列表
         * @return {@link ListNode}
         */
        public static ListNode mergeKLists(ListNode[] lists) {
            if (lists == null || lists.length == 0) {
                return null;
            }
            return merge(lists, 0, lists.length - 1);
        }
    
        private static ListNode merge(ListNode[] lists, int left, int right) {
            if (left >= right) {
                return lists[left];
            }
            int mid = left + ((right - left) >> 1);
            ListNode l1 = merge(lists, left, mid);
            ListNode l2 = merge(lists, mid + 1, right);
            return mergeTwoLists(l1, l2);
        }
    
        public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
            ListNode sentry = new ListNode(-999);
            ListNode point = sentry;
            while (list1 != null && list2 != null) {
                if (list1.val < list2.val) {
                    point.next = list1;
                    list1 = list1.next;
                } else {
                    point.next = list2;
                    list2 = list2.next;
                }
                point = point.next;
            }
            if (list1 == null) {
                point.next = list2;
            } else {
                point.next = list1;
            }
            return sentry.next;
        }
    

    Idea:
    分治思想。最大限度利用每个list都有序的特点。
    相似题目:21 合并两个有序链表

    Reslut:

  • 相关阅读:
    git拉取线上新分支拉不下来
    contenteditable属性,让div也可编辑
    给2021做一个小结
    http协议相关面试题
    C# 相对路径 系统路径
    开源数据库全接触-MongoDB,Cassandra,Hypertable,CouchDB,Redis,HBase,Voldemort 等简介
    WebForms,MVC和网页的OAuth / OpenID的支持
    HTTP head 详解
    CAB 文件注册及内部INF 文件说明
    【ECJTU_ACM 11级队员2012年暑假训练赛(8) I Lucky Division】
  • 原文地址:https://www.cnblogs.com/supermingjun/p/16126640.html
Copyright © 2020-2023  润新知