合并K个升序链表

119 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

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

  • 请你将所有链表合并到一个升序链表中,返回合并后的链表。 示例 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 = []
输出: []

输入:lists = [[]]
输出:[]

思路分析

  • 根据题目知道链表数组内的链表都是有序的,如果 链表数组长度为 nn 我们可能会想出用小根堆来维护 nn 个链表的下标,在每次取出其中一个最小值链表的 valuevalue 后都会自动调节。此时我们需要同时维护 nn 个链表,好像有有一点复杂,不妨多想想还有其他方法吗?
  • 既然是有序链表数组,我们可以带着分治的思想来思考。发现可以把链表数组不断分割,链表数组为 1 或 0 时就可以归并了,因为我们分割成了许许多多的小链表数组,形成了多路自底向上的归并。如下图(图源网络)。

51b4a07fa6626ec0d120c8b0f53746a4.png

AC 代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int n = lists.length;
        if (n == 0) return null;
        return merge(lists, 0, n - 1);
    }

    private ListNode merge(ListNode[] lists, int left, int right) {
        if (left == right) return lists[left];
        int mid = left + (right - left) / 2;

        ListNode leftList = merge(lists, left, mid);
        ListNode rightList = merge(lists, mid + 1, right);
        ListNode tempList = new ListNode();
        ListNode head = tempList;

        while (leftList != null && rightList != null) {
            if (leftList.val <= rightList.val) {
                tempList.next = new ListNode(leftList.val);
                tempList = tempList.next;
                leftList = leftList.next;
            } else {
                tempList.next = new ListNode(rightList.val);
                tempList = tempList.next;
                rightList = rightList.next;
            }
        }
        if (leftList != null) {
            tempList.next = leftList;
        }
        if (rightList != null) {
            tempList.next = rightList;
        }
        return head.next;
    }
}

总结

  • 这也是一道 leetcode 上 hard 难度的题目,仔细分析后发现也没有我们想的那么难了,只要在细节上处理好了,遇到的问题也就不再是问题了!