一、题目
给你单链表的头节点 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]
二、代码
思路:
- 首先找到四个节点:prev,succ,leftNode,rightNode(leftNode和rightNode是要反转的头尾节点,prev是leftNode之前的节点,succ是rightNode之后的节点)
- 将要反转的子链表先断开(prev和rightNode的next均设为nullptr)
- 将子链表反转(方法可见 leetcode 206. 反转链表)
- 然后将反转后的子链表和原来的连接起来
- 为了避免left==1要分类讨论的情况,在head前面设置一个虚拟头结点,最后返回这个虚拟头结点的next即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reverseList(ListNode* head){
ListNode* prev=nullptr,*cur=head,*next;
while(cur){
next=cur->next;
cur->next=prev;
prev=cur;
cur=next;
}
}
ListNode* reverseBetween(ListNode* head, int left, int right) {
// 添加一个虚拟头结点,避免left=1的情况
ListNode* vHead=new ListNode(0,head);
ListNode* prev=vHead,*succ,*leftNode,*rightNode;
for(int i=1;i<left;++i){
prev=prev->next;
}
leftNode=prev->next;
rightNode=prev;
int len=right-left+1;
for(int i=1;i<=len;++i){
rightNode=rightNode->next;
}
succ=rightNode->next;
// 截断链表
prev->next=nullptr;
rightNode->next=nullptr;
reverseList(leftNode);
// 重新连接
prev->next=rightNode;
leftNode->next=succ;
return vHead->next;
}
};