类比 #206反转链表
首先找到left的前一个结点与right结点,并且保存左节点left和右节点right的下一个结点,将子链表截取出来并反转,最后拼接到原链表即可,具体细节详见代码,记得设置哑结点,避免头结点需要特殊处理。
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:
ListNode *reverseList(ListNode *head) {//翻转链表 同 206反转链表
ListNode *prev = nullptr;
ListNode *cur = head;
while(cur) {
ListNode *tmp = cur->next;
cur->next = prev;
prev = cur;
cur = tmp;
}
return prev;//新链表头结点
}
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(head==nullptr||head->next==nullptr)return head;
//设置一个虚拟头结点
ListNode *dummy = new ListNode(-1,head);
ListNode *pre = dummy;
//寻找left的前一个结点
for(int i = 0;i<left-1;++i) {
pre = pre->next;
}
//寻找right结点
ListNode *rightNode = pre;
for(int i = 0;i<right-left+1;++i) {
rightNode = rightNode->next;
}
//保存左节点和右节点的下一个结点
ListNode *leftNode = pre->next;
ListNode *succ = rightNode->next;
//截断
pre->next = nullptr;
rightNode->next = nullptr;
//翻转子链表 并与原先链表拼接
pre->next = reverseList(leftNode);
leftNode->next = succ;
return dummy->next;
}
};