[路飞]_反转链表 II

166 阅读2分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

题目描述

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

力扣(LeetCode)leetcode-cn.com/problems/re…

解题思路

  1. 找到 left 和 right 两个节点,并且记录 left 的前节点为 prevLeft,right 的下个节点为 rightNext
    • 从 head 往右走 left - 1 步就是 left
    • 从 left 往右走 right - left 步就是 right
  2. 找到 left 、right 后,把 left 的下个节点至 right 的前个节点进行翻转
    • curr 指向 left,从 left 开始翻转
    • prev 指向 rightNext,这样翻转子链表时,头节点正好和后半段连接上
    • 定义好 curr、prev 就可以对子链表进行翻转了
  3. 翻转完子链表后把前半段和子链表的头拼接上,即 preLeft.next = rightNode
  4. 返回 head

举个例子

[1, 2, 3, 4, 5, 6, 7],left = 3,right = 5

第一步: 找到第 3 个节点和第 5 个节点

Kapture 2021-11-25 at 15.31.11.gif

第二步:翻转 left 至 right 子链表,并将子链表的尾指向 right 的下个节点,将 left 的前个节点指向子链表的头节点

Kapture 2021-11-25 at 21.55.14.gif

代码实现

var reverseBetween = function(head, left, right) {
  if (!head || !head.next || left === right) return head

  let curr = head
  let prev = next = null
  let leftNode = prevLeft = rightNode = rightNext = null
  
  //找到 left 要走的步数
  let step = left - 1

  //找到第 left 个节点,和 left前一个节点
  while (step--) {
    prevLeft = curr
    curr = curr.next
  }
  leftNode = curr
  prevLeft.next = null

  //找到第 right 个节点,和 right 的下一个节点
  step = right - left
  while (step--) {
    curr = curr.next
  }
  rightNode = curr
  rightNext = curr.next
  rightNode.next = null

  //翻转 left 至 right 之间的子链表
  curr = leftNode
  prev = rightNext

  while (curr) {
    next = curr.next
    curr.next = prev
    prev = curr
    curr = next
  }

  //把子链表和前半段拼接
  prevLeft.next = rightNode

  return head
}

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