分治法-合并 K 个升序链表

62 阅读1分钟

合并 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

分析

解法一:用小顶堆,初始化放入K个,然后依次取出堆顶元素,加入新链表,把取出来的元素的下个节点重新入堆。

解法二:分治法。

  1. 先对原问题进行拆分,每次数组进行对半拆分,直至只有一个链表,这是就可以返回
  2. 分别拿到左边和右边的有序链表,然后进行合并。(类似于归并排序的merge操作)

代码

解法一

    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue<ListNode> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(o -> o.val));
        for (ListNode head : lists) {
                  if (head != null) {

                priorityQueue.offer(head);
            }
        }

        ListNode listHead = new ListNode(-1, null);
        ListNode tail = listHead;
        while (!priorityQueue.isEmpty()) {
            ListNode node = priorityQueue.poll();
            tail.next = node;
            tail = node;

            if (node.next != null) {
                priorityQueue.offer(node.next);
            }

        }
        return listHead.next;
    }

解法二

 public ListNode mergeKLists(ListNode[] lists) {
        if (lists.length == 0) {
            return null;
        }
        return process(0, lists.length - 1, lists);
    }

    //先分,后合并
    public ListNode process(int start, int end, ListNode[] lists) {
        if (start == end) {
            return lists[start];
        }
        int mid = (start + end) / 2;
        ListNode leftOrdered = process(start, mid, lists);
        ListNode rightOrdered = process(mid + 1, end, lists);

        return merge(leftOrdered, rightOrdered);

    }

    //合并操作
    private ListNode merge(ListNode leftOrdered, ListNode rightOrdered) {
        if (leftOrdered == null) {
            return rightOrdered;
        }
        if (rightOrdered == null) {
            return leftOrdered;
        }

        PriorityQueue<ListNode> heap = new PriorityQueue<>((o1, o2) -> o1.val - o2.val);
        heap.add(leftOrdered);
        heap.add(rightOrdered);
        ListNode sentinel = new ListNode();
        ListNode p = sentinel;
        while (heap.size() > 0) {
            ListNode node = heap.poll();
            p.next = node;
            p = node;
            if (node.next != null) {
                heap.add(node.next);
            }
        }
        return sentinel.next;
    }