25.反转部分链表【LC92】

121 阅读1分钟

题目:

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

image.png

核心思路:

本题的关键点有两部分,一部分是指定位置反转,另一部分是三段链表的衔接动作。

剖析一下整体思路:

  • 需要一个索引标识idx,作为遍历的控制位,对整个链表拆分三个区间: [1, left), [left, right],(right, 最后]

  • 需要一个新链表头newHeader

  • 需要一个新链表当前节点指针 curHeader

此时,就可以进入链表1段的遍历了。

  • 需要一个反转链表头revHeader
  • 需要一个反转辅助指针p

此时,遍历并对链表段2中国呢所有[left, right]之间的节点进行反转,拼接。

注意,为了进行后三段链表的拼接,我们要提前做好一些处理:

1)链表段2与链表段3的拼接
当idx===left时,做好指针记录,指针q指向当前节点,也就是指向反转后2段链表的最后一个节点。

2)链表段1与链表段2的拼接
当idx===right时,将curHeader.next(原来curHeader还在指向链表1段的最后一个节点)指向revHeader
让curHeader指向q,指向反转后链表2段的最后一个节点,继续拼接链表3段

解:

var reverseBetween = function (head, left, right) {
  let idx = 1; // 控制位,控制左右界限
  const newHeader = {}; // 新的链表头
  let curHeader = newHeader; // 当前位头指针
  let revHeader = null; // 链表反转部分头指针
  let p = null; // 链表反转辅助位
  let q = null; // 反转链表最后一个节点,用于衔接最后一段链接。
  while (head) {
    if (idx < left) {
      curHeader.next = head;
      curHeader = curHeader.next;
      head = head.next;
    } else if (left <= idx && right >= idx) {
      p = head;
      head = head.next;
      p.next = revHeader;
      revHeader = p;
      if (left === idx) {
        q = p; // 反转链表的最后一个节点,用于衔接最后一个链表3,做好指针记录
      }
      if (right === idx) {
        curHeader.next = revHeader; // 链表2反转完毕,链表1衔接链表2
        curHeader = q; // 将当前位指针指向链表2的最后一个节点
      }
    } else {
      curHeader.next = head; // step3: 接着进入最后一段链表
      curHeader = curHeader.next;
      head = head.next;
    }
    idx++;
  }
  return newHeader.next
};

———— 前端、Javascript实现、算法、刷题、leetcode