刷题使我快乐,满脸开心.jpg
谢谢大家的支持!点个在看再走哟~

  • 来源:力扣(LeetCode)
  • 链接:https://leetcode.cn/problems/reverse-linked-list-ii/
  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目

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

示例 1:

输入: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

进阶: 你可以使用一趟扫描完成反转吗?

思路

思路详情参见题解 https://leetcode.cn/problems/reverse-linked-list-ii/solutions/37247/bu-bu-chai-jie-ru-he-di-gui-di-fan-zhuan-lian-biao/

我的思路跟这篇题解基本一致,不过这篇题解讲的更加清晰透彻,需要则可以移步LeetCode网站看下。
定位不同,我这边就只简单聊下思路:
1、反转部分有两个注意点

  • 一个是反转起点,所以首先是要找到反转起点,其他情况下直接步进即可
  • 一个是反转终点,所以需要一个长度限制,表明反转终点,另外需要一个变量来存储反转后的剩余尾部,方便后续拼接

2、反转部分的代码由递归反转链表演变而来,详情可以参见这篇的递归解法 LeetCode-206.反转链表

代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

func reverseBetween(head *ListNode, left int, right int) *ListNode {
    // 找到反转起始位置,反转后退出,返回反转后头结点
    if left == 1 {
        keepTail := &ListNode{}
        return reverseN(head, right, &keepTail);
    }
    // 前进到反转的起点
    head.Next = reverseBetween(head.Next, left - 1, right - 1);
    return head;
}

func reverseN(head *ListNode, n int, keepTail **ListNode) *ListNode {
    if n == 1 { 
        // 记录需要保留的尾部节点
        *keepTail = head.Next;
        return head;
    }
    // 以 head.next 为起点,共需要反转前 n 个节点,减去此层,还有n - 1层
    last := reverseN(head.Next, n - 1, keepTail);

    head.Next.Next = head;
    // 让反转之后的 head 节点和后面的节点连起来,
    // 不用担心中间会乱,因为,退出后的下一轮递归会将此改为原本顺序的上一节点
    // 最终,只会需要反转部分中,原本顺序最前的节点指向keepTail,也是我们想要的结果
    head.Next = *keepTail;
    return last;
}

看到这里了,点个赞点个在看呗!~ 多谢啦!~