刷题使我快乐,满脸开心.jpg
谢谢大家的支持!点个在看再走哟~
- 来源:力扣(LeetCode)
- 链接:https://leetcode.cn/problems/reverse-linked-list-ii/
- 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目
给你单链表的头指针 head
和两个整数 left
和 right
,其中 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;
}
看到这里了,点个赞点个在看呗!~ 多谢啦!~