LeetCode合并 k个升序链表

问题:

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

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

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]

输出:[1,1,2,3,4,4,5,6]

解释:链表数组如下:

javascript 复制代码
[
  1->4->5,
  1->3->4,
  2->6
]

将它们合并到一个有序链表中得到。

javascript 复制代码
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []

输出:[]

示例 3:

输入:lists = [[]]

输出:[]

解题思路

将所有值放进数组中排序,再新造ListNode

javascript 复制代码
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
 
var mergeKLists = function (lists) {
    // 初始化一个数组来存储所有链表的值
    const list = [];
    // 遍历所有链表
    for (let i = 0; i < lists.length; i++) {
        let node = lists[i];
        // 遍历链表并收集值
        while (node) {
            list.push(node.val);
            node = node.next;
        }
    }
    // 排序所有值
    list.sort((a, b) => a - b);
    // 创建结果链表的头节点
    const res = new ListNode();
    // 使用哑节点简化链表构建过程
    let now = res;
    // 构建排序后的链表
    for (let i = 0; i < list.length; i++) {
        now.next = new ListNode(list[i]);
        now = now.next;
    }
    // 返回合并和排序后的链表的头节点
    return res.next;
};

代码解释:

这段代码通过嵌套循环遍历了 lists 数组中的每个链表。lists 数组包含了 k 个链表,每个链表由 ListNode 对象组成。以下是遍历过程的详细解释

1.初始化外部循环:

使用 for 循环初始化索引 i,从 0 开始,直到 lists.length(即 k),因为 lists 数组的长度表示链表的数量。

2.获取当前链表:

在每次迭代中,lists[i] 获取 lists 数组中第 i 个链表的引用。

3.初始化内部循环:
let node = lists[i] 声明了一个变量 node,它指向当前链表的头节点。

4.遍历当前链表:

使用 while 循环遍历当前链表。循环条件是 node 不为 null,即链表尚未到达末尾。

5.收集节点值:

while 循环内部,node.val 获取当前节点的值,并将其添加到 list 数组中:list.push(node.val)

6.移动到下一个节点:
node = node.next 将 node 指针移动到链表的下一个节点。

7.继续遍历:

如果 node 仍然不是 null,则继续循环,重复步骤 5 和 6。

8.完成当前链表的遍历:

nodenull 时,while 循环结束,表示当前链表已遍历完毕。

9.移动到下一个链表:
for 循环的下一次迭代将 i 增加,并将 node 重置为下一个链表的头节点。

10.完成所有链表的遍历:

i 达到 lists.length 时,for 循环结束,表示所有链表都已遍历完毕。
示例:

假设 lists 包含以下链表:

javascript 复制代码
lists[0]: 1 -> 3 -> 5
lists[1]: 2 -> 4
lists[2]: 6

遍历过程如下:

i = 0: node 从 1 遍历到 5,将值推入 list
i = 1: node 从 2 遍历到 4,将值推入 list
i = 2: node 从 6 开始,将其值推入 list

最终,list 数组包含所有链表的值 [1, 3, 5, 2, 4, 6]

这种嵌套循环的方法确保了所有 k 个链表中的所有节点都被访问并收集其值。

在这个 mergeKLists 函数中,res 是一个新创建的 ListNode 实例,用作合并后链表的头节点。然而,这个头节点最初是空的,它的 next 指针被初始化为 nullnow 指针用于在构建新链表的过程中遍历链表并添加新的节点。

解释 resnow

  • res 是合并后链表的头节点,但在初始化时,res.nextnull
  • now 是一个辅助指针,用于在链表构建过程中指向当前正在操作的节点。

构建链表的过程:

1.首先,创建一个空的头节点 res

2.使用 now 指针从 res 开始,逐个添加新节点到链表中。

3.在每次迭代中,将 now.next 设置为一个包含当前值的新 ListNode,然后将 now 移动到这个新节点。

为什么返回 res.next 而不是 now.next:

在链表构建的最后,now 指针位于链表的末尾(最后一个节点)。如果返回 now.next,这将返回链表的最后一个节点之后的 null 指针,这不是链表的有效部分。

res 是链表的头节点,即使在迭代过程中 now 移动了,res 始终指向链表的开始。因此,res.next 是链表的第一个有效节点,这是我们想要返回的。

总结:

返回 res.next 是因为我们想要返回合并后链表的头节点,它是链表的第一个有效节点。now 指针仅用于遍历和构建链表,而 res 始终保持对链表头部的引用。

相关推荐
墨染点香2 小时前
LeetCode 刷题【139. 单词拆分】
算法·leetcode·职场和发展
Tisfy4 小时前
LeetCode 3346.执行操作后元素的最高频率 I:滑动窗口(正好适合本题数据,II再另某他法)
算法·leetcode·题解·滑动窗口·哈希表
熬了夜的程序员5 小时前
【LeetCode】94. 二叉树的中序遍历
数据结构·算法·leetcode·职场和发展·深度优先
熬了夜的程序员5 小时前
【LeetCode】92. 反转链表 II
数据结构·算法·leetcode·链表·职场和发展·排序算法
景早6 小时前
力扣1. 两数之和
数据结构·算法·leetcode
快乐的钢镚子9 小时前
【leetcode hot 100】49.字母异位词分组
python·leetcode
tao35566715 小时前
【Python刷力扣hot100】42. Trapping Rain Water
开发语言·python·leetcode
Miraitowa_cheems15 小时前
LeetCode算法日记 - Day 88: 环绕字符串中唯一的子字符串
java·数据结构·算法·leetcode·深度优先·动态规划
小白菜又菜16 小时前
Leetcode 1518. Water Bottles
算法·leetcode·职场和发展