[路飞]_LeetCode_23. 合并K个升序链表

170 阅读1分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看: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 = []
输出:[]

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

来源:力扣(LeetCode)leetcode-cn.com/problems/me…

解题思路

第一种思路是把数组中的链表按顺序合并; 第二种思路是通过分治的方式,把数组对半拆分,再对两边子数组分治做合并操作。直到拆分不了时,左右两个子数组中剩下一个链表,合并这两个链表为一个链表。两两合并后得到的新链表再依次往上两两合并,最终合并成一个链表。

这里我们使用第二种方式来解这道题。

代码实现

var mergeKLists = function (lists) {
    return merge(lists, 0, lists.length - 1)
}

var merge = function (lists, left, right) {
    if (left === right) return lists[left]
    if (left > right) return null

    // 从数组中间平分,通过分治的方式合并链表
    const mid = (left + right) >> 1
    // 合并数组左边链表
    const l1 = merge(lists, left, mid)
    // 合并数组右边链表
    const l2 = merge(lists, mid + 1, right)
    return mergeTwoList(l1, l2)
}

function mergeTwoList(l1, l2) {
    if (!l1 || !l2) return l1 ? l1 : l2
    const tail = new ListNode()

    if (l1.val <= l2.val) {
        // 如果 l1 的表头小于等于 l2 的表头,则把 l1 取出来
        // 再将 l1 的 next 和 l2 合并,返回的结果再和 l1 连接
        tail.next = l1
        l1.next = mergeTwoList(l1.next, l2)
    } else {
        // 如果 l1 的表头大于 l2 的表头,则把 l2 取出来
        // 再将 l2 的 next 和 l1 合并,返回的结果再和 l2 连接
        tail.next = l2
        l2.next = mergeTwoList(l1, l2.next)
    }

    //返回临时节点的下个节点
    return tail.next
}

如有错误欢迎指出,欢迎一起讨论!