手摸手提桶跑路——LeetCode23. 合并K个升序链表

127 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,点击查看活动详情

题目描述

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

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

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

解题思路——遍历

这道题要看清楚,题目给我们的是一个 链表数组,数组的每个元素都是一个链表的 表头,且每个链表都是 升序排序 的。

题目要求我们对这些升序链表进行合并。如果是二维升序数组进行合并,想必大家都会,最简单暴力的方法就是将二维数组“拍平”,也就是进行 flat 操作,使之变为一维乱中有序数组,然后对其进行升序排序,就是一个合并后的升序数组了。

这道题目就是将数组换成了链表而已。具体步骤如下:

  1. 初始化一个存放节点值的变量 arr
  2. 遍历链表数组 lists,其中的每个元素,都是一个表头,我们根据这个表头去遍历链表,将每个 节点的值 都存入结果数组 arr 中。
  3. 遍历完所有的链表后对 arr 进行排序。
  4. 初始化一个哨兵节点 res,用于后续新建节点的拼接。
  5. 遍历 arr 数组,其中的每个元素都创建一个对应的链表节点,然后拼接到 res尾部
  6. 输出 res.next 就是题解。

题解

var mergeKLists = function(lists) {
    let res = new ListNode(null);
    let arr = lists.reduce((f, c) => {
        while(c) {
            f.push(c.val);
            c = c.next;
        }
        return f;
    }, []).sort((a, b) => a - b);

    let t = res;
    for(let i=0; i<arr.length; ++i) {
        t.next = new ListNode(arr[i]);
        t = t.next;
    }
    return res.next;
};

捕获.PNG

解题思路——两两合并

可以创建一个链表节点 ans,遍历 lists,依次将链表与 ans 两两合并,遍历结束后就是一个升序链表了。