LeetCode 1669:合并两个链表

192 阅读2分钟

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

LeetCode 1669:合并两个链表

题目描述

给你两个链表 list1 和 list2 ,它们包含的元素分别为 n 个和 m 个。

请你将 list1 中下标从 a 到 b 的全部节点都删除,并将list2 接在被删除节点的位置。

下图中蓝色边和节点展示了操作后的结果:

解题思路

思路一

  1. 新建哑节点dummy node,便于返回结果;

  2. 分别找到下标为a - 1、b + 1的节点标记为prev, curr;

for (let i = 1; i <= a; i++) {
  prev = curr;
  curr = curr.next;
}
for (let j = a; j <= b; j++) {
  curr = curr.next;
}
  1. 找到链表list2的最后一个节点
 var tail = list2;
  while (tail.next != null) {
    tail = tail.next;
  }
  1. 然后将prev节点的next指向list2list2的尾节点tailnext指向curr;
  2. 最后返回dummy.next

完整代码如下:

/**
 * @param {ListNode} list1
 * @param {number} a
 * @param {number} b
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeInBetween = function (list1, a, b, list2) {
  let dummy = new ListNode(0, list1);
  let prev,
    curr = list1;
  for (let i = 1; i <= a; i++) {
    prev = curr;
    curr = curr.next;
  }
  for (let j = a; j <= b; j++) {
    curr = curr.next;
  }
  let tail = list2;
  while (tail.next != null) {
    tail = tail.next;
  }
  prev.next = list2;
  tail.next = curr;
  return dummy.next;
};

时间复杂度: O(b + m); 遍历b次找到下标b的节点curr, 遍历m次找到链表list2的尾节点, 所以时间复杂度为O(b + m);  

空间复杂度: O(1);

或者优化下:

var mergeInBetween = function(list1, a, b, list2) {
    let curr = list1;
    // 遍历到 a 前面一个节点, a 前面的节点无需操作
    for (let i = 1; i < a ; i++) {
      curr = curr.next;
    }
    
    // 过滤掉不需要的节点
    let node = curr.next;
    for (let i = a; i <= b ; i++) {
      node = node.next;
    }    
    
    // 从 b + 1 位置开始 插入list2
    curr.next = list2
    while (curr.next) {
      curr = curr.next;
    }

    // list2全部插入之后 指向list1过滤后的所有节点
    curr.next = node;
    return list1;
}; 

以上代码中 没有使用哑节点,最终直接返回list1;使用两个临时遍历curr和node

参考资料

1669. 合并两个链表 - 力扣(LeetCode)