zoukankan      html  css  js  c++  java
  • Hard | LeetCode 23. 合并K个升序链表 | 分治 | 优先队列

    23. 合并K个升序链表

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

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

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

    方法一:

    根据前面的一道题 Easy | 剑指 Offer 25. 合并两个排序的链表 , 我们可以对两个链表进行合并。本题的合并K个链表可以依次进行合并。

    public ListNode mergeKLists(ListNode[] lists) {
        ListNode ans = null;
        for (int i = 0; i < lists.length; ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }
    
    public ListNode mergeTwoLists(ListNode a, ListNode b) {
        if (a == null || b == null) {
            return a != null ? a : b;
        }
        ListNode head = new ListNode(0);
        ListNode tail = head, aPtr = a, bPtr = b;
        while (aPtr != null && bPtr != null) {
            if (aPtr.val < bPtr.val) {
                tail.next = aPtr;
                aPtr = aPtr.next;
            } else {
                tail.next = bPtr;
                bPtr = bPtr.next;
            }
            tail = tail.next;
        }
        tail.next = (aPtr != null ? aPtr : bPtr);
        return head.next;
    }
    

    方法二: 分治合并

    类似于Hard | 剑指 Offer 51. 数组中的逆序对 | 归并排序 里的归并排序, 先两两归并, 归并完后再两两归并。

    public ListNode mergeKLists(ListNode[] lists) {
        return merge(lists, 0, lists.length - 1);
    }
    
    public ListNode merge(ListNode[] lists, int l, int r) {
        if (l == r) {
            return lists[l];
        }
        if (l > r) {
            return null;
        }
        int mid = (l + r) >> 1;
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
    }
    

    方法三: 优先队列

    对K个值取最小值时, 可以使用优先的队列的方式。

    class Solution {
        // 对链表节点进行封装
        class Status implements Comparable<Status> {
            int val;
            ListNode ptr;
    
            Status(int val, ListNode ptr) {
                this.val = val;
                this.ptr = ptr;
            }
    
            public int compareTo(Status status2) {
                return this.val - status2.val;
            }
        }
    
        PriorityQueue<Status> queue = new PriorityQueue<Status>();
    
        public ListNode mergeKLists(ListNode[] lists) {
            for (ListNode node: lists) {
                if (node != null) {
                    queue.offer(new Status(node.val, node));
                }
            }
            ListNode head = new ListNode(0);
            ListNode tail = head;
            while (!queue.isEmpty()) {
                Status f = queue.poll();
                tail.next = f.ptr;
                tail = tail.next;
                if (f.ptr.next != null) {
                    queue.offer(new Status(f.ptr.next.val, f.ptr.next));
                }
            }
            return head.next;
        }
    }
    
  • 相关阅读:
    CentOS 5.3 挂载 读写 ntfs硬盘
    Linux基础教程
    信息安全技术实用教程
    单片机原理与应用技术
    【36.11%】【codeforces 725C】Hidden Word
    【37.74%】【codeforces 725D】Contest Balloons
    【16.67%】【codeforces 667C】Reberland Linguistics
    【16.05%】【codeforces 664B】Rebus
    【record】10.17..10.23
    【23.33%】【codeforces 664C】International Olympiad
  • 原文地址:https://www.cnblogs.com/chenrj97/p/14295202.html
Copyright © 2011-2022 走看看