春招打卡|反转链表2|go实现

81 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述

给定单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表 。输入:head = [1,2,3,4,5], left = 2, right = 4 输出:[1,4,3,2,5]

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

要求:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • 500 <= Node.val <= 500
  • 1 <= left <= right <= n

二、思路分析

  1. 与反转链表1不同的地方在于,只反转链表中的一段节点,就需要记录被反转链表头结点的前一个节点,以及最后一个节点的后一个节点,用于最后拼接反转后的链表。
  2. 首先从头结点向左遍历left个位置,找到需要被反转的链表的前置节点。
  3. 再从该前置节点遍历right-left+1个位置,找到被反转链表的最后一个节点。
  4. 到这一步骤问题就被简化为反转链表的问题,调用reverseList 反转需要被反转的链表。
  5. 记录了前置节点和后续节点,再将其拼接在一块,返回结果。
  6. 这种方式需要遍历两次,第一次是寻找前置节点,使用for循环遍历一次,第二次是寻找后置节点for循环遍历一次。

三、AC 代码

func reverseBetween(head *ListNode, left int, right int) *ListNode {
    //dummynode 头结点,避免边界操作
    dummynode := &ListNode{Next:head}
    pre := dummynode
    //找到需要反转的left左边的节点
    for i := 0;i<left-1;i++ {
        pre = pre.Next
    }
    rightnode := pre
    //寻找rightnode
    for i := 0 ;i<right-left+1;i++{
        rightnode = rightnode.Next
    }
    //leftnode,rightnode为截取出的链表,切断
    leftnode := pre.Next
    pre.Next = nil
    rightrightNode := rightnode.Next
    rightnode.Next = nil
    //reverseList
    reverseList(leftnode)
    //反转后rightnode在左边,leftnode在右边,拼接到一起
    pre.Next = rightnode
    leftnode.Next = rightrightNode
    return dummynode.Next
}
func reverseList(head *ListNode)  {
    var pre *ListNode
    cur := head
    for cur != nil {
        next := cur.Next
        cur.Next = pre
        pre = cur
        cur = next
    }
}

四、总结

反转链表是一道常考的经典题目,反转链表2需要使用到反转链表的方法。在细节上需要处理前置节点和后置节点。需要注意的是,被反转链表的头尾节点,在反转前分别为leftnoderightnode,反转后头结点为rightnode,尾节点为leftnode ,并且在反转前首先要切割开需要翻转的链表在代码中为pre.Next = nil rightnode.Next = nil