[路飞]_程序员必刷力扣题: 92. 反转链表 II

841 阅读2分钟

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

92. 反转链表 II

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

示例 1: image.png

输入: head = [1,2,3,4,5], left = 2, right = 4
输出: [1,4,3,2,5]

示例 2:

输入: head = [5], left = 1, right = 1
输出: [5]

提示:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n   进阶:  你可以使用一趟扫描完成反转吗?

遍历+改变指针

思路

反转部分链表我们这里就需要把需要反转的部分单独领出来,然后对它进行反转

  • 为了省去过多边界处理,我们生成一个新节点preHead衔接在链表头部
  • 声明一个指针newHead用来遍历链表
  • 声明一个index用来记录当前到达第几个节点
  • 在遍历过程中找到需要反转的部分,进行反转后,再重新衔接起整个链表

    声明四个节点需要

    pLeft:原链表中子链表的前一个节点

    pRight: 原链表中子链表的后一个节点

    childLeft: 子链表的头结点

    childRight:子链表的尾结点

  • 将子链表分割出来进行反转
  • 按照pLeft->childRight---childLeft->pRight的顺序进行重新连接 最后返回preHead.next
var reverseBetween = function (head, left, right) {
    var preHead = new ListNode('head')
    preHead.next = head
    var newHead = preHead
    
    var index = 0
    var pLeft, pRight, childLeft, childRight
    while (newHead) {
        
        if (index === left - 1) {
            pLeft = newHead
            childLeft = newHead.next
        }
        if (index === right) {
            childRight = newHead
            pRight = newHead.next
        }
        newHead = newHead.next
        index++
    }
    pLeft.next = null
    childRight.next = null
    reverseList(childLeft)
    pLeft.next = childRight
    childLeft.next = pRight

    return preHead.next
};
var reverseList = function (head) {
    var pre = null
    var newHead = head
    while (newHead) {
        var next = newHead.next
        newHead.next = pre
        pre = newHead
        newHead = next
    }
};

一次遍历

思路

一次遍历就是在遍历到需要反转的节点时进行逐一处理,例如

1->2->3->4->5 2 4

移动3到1后

1->3->2->4->5

移动4到1后

1->4->3->2->5

  • 为了省去过多边界处理,我们生成一个新节点preHead衔接在链表头部
  • 在遍历过程中我们要逐一处理需要反转的部分,需要生命以下几个变量

    声明四个节点需要

    pLeft:原链表中 子链表的前一个节点

    preCurr: 当前节点的前一个节点,在子链表中其实一直都是未反转前的第一个节点,即原链表中left的位置,因为这个节点会被反转,一直指向下一个节点,所以在子链表范围,每个当前节点的前一个节点都是他

    childLeft: 子链表的第一个节点,即pLeft的下一个节点,实时更新

  • 处理流程如下

    pLeft ->curr->childLeft->next(剩余节点)

最后返回preHead.next

var reverseBetween = function(head, left, right) {
   var preHead = new ListNode('head')
   preHead.next = head
   var index=0
   var newHead = preHead
   var pLeft,preCurr
   while(newHead){
       var next=newHead.next
       var curr=newHead
       if(index===left-1){
           pLeft=newHead
           preCurr = childLeft=newHead.next
       }
       if(index>left&&index<=right){
           pLeft.next=curr
           curr.next=childLeft
           preCurr.next=next
           
           childLeft=curr
       }
       
       newHead=next
       index++
   }
   return preHead.next
};
};