思路:
- 可以将链表划分为三个部分,
- 第一部分要反转的左侧,需要一个指针指向该部分的最后一个结点(需要考虑,直接从头开始反转的情况)
- 中间部分需要用到两个指针抓住他们(或者你说定位也行)
- 右侧部分需要用到一个指针,指向最前面的一个结点
- 反转中间部分
- 最后,将三个部分连起来
/**
* 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:
ListNode* reverseBetween(ListNode* head, int left, int right) {
//去除捣蛋的部分
if(head == nullptr || head->next == nullptr)return head;
ListNode* per = nullptr;
ListNode* cur = head;
//左侧的尾巴
ListNode* ET = nullptr;
//中间部分的头和尾
ListNode* CH = nullptr;
ListNode* CT = nullptr;
//右侧的头
ListNode* RH = head;
int i = 1;
while(cur != nullptr && i <= left){
//寻找到左侧部分的终点
if(i == left){
//说明此时已经到达了中间部分,当前结点的前一个结点是左侧部分的最后一个结点
ET = per;
CH = cur;
CT = cur;
break;
}
i++;
per = cur;
cur = cur->next;
}
if(ET != nullptr){
ET->next = nullptr;
}
//到这里cur指向了中间部分的头位置,需要开始遍历中间部分的结点,直到右侧部分的头为止
while(cur != nullptr && i <= right){
if(i == right){
//此时cur到达中间部分的最右侧,下一个结点就是右侧部分的头
RH = cur->next;
CT = cur;
break;
}
i++;
per = cur;
cur = cur->next;
}
if(CT != nullptr){
CT->next = nullptr;
}
//开始逆序中间部分
CH = reverseList(CH);
//此时中间部分已经逆序完毕,需要找到他的尾结点
cur = CH;
CT = CH;
while(cur != nullptr){
CT = cur;
cur = cur->next;
}
//开始拼接三个部分.
//head可能会变,需要考虑
if(ET != nullptr){
ET->next = CH;
}else{
//如果左侧部分为空,那head肯定也得变
head = CH;
}
if(CT != nullptr){
CT->next = RH;
}else{
head = RH;
}
return head;
}
ListNode* reverseList(ListNode* head){
if(head == nullptr || head->next == nullptr)return head;
ListNode* per = nullptr;
ListNode* cur = head;
while(cur != nullptr){
ListNode* lat = cur->next;
cur->next = per;
per = cur;
cur = lat;
}
return per;
}
};