/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
if (!head) return head;
if (m <= 0 || n <= 0) return head;
if (m >= n) return head;
ListNode* left = head;
ListNode* right = NULL;
ListNode* begin = head;
ListNode* end = head;
if (m == 1) {
left = NULL;
begin = head;
} else {
while ((m > 2) && left) {
left = left->next;
m--;
}
if (!left) return head;
begin = left->next;
if (!begin) return head;
}
while (n > 1 && end) {
end = end->next;
n--;
}
if (!end) return head;
right = end->next;
ListNode* pre = NULL;
ListNode* cur = begin;
ListNode* next = NULL;
while (cur != right) {
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
begin->next = right;
if (left) {
left->next = end;
} else {
head = end;
}
return head;
}
};
四个指针,分别保存 left/right/start/end 结点,left start end= head,right = null
前三步,找到对应m与n值对应的结点:
1. 三种情况返回原值head,①区间不合法(m>=n || m/n <= 0),②头结点不存在
2. 如果m=1,则与 链表反转完全相同 ,说明从第一个结点开始反转,直接将 left = null , 从头结点开始
反之,找到起点m值对应的那个结点的前一个结点,存为left(若此时的left为空,则越界,返回head),begin 为left下一个结点,即m值对应的结点(同时判断begin存在与否,若不存在begin,则返回head)
3.再找结尾n值对应的end结点(若此时的end为空,则越界,返回head),right为end之后的结点
最后排序为left begin(m) end(n) right
找到对应的结点之后,方法与反转链表相同:新开pre,cur,next结点,只要cur!= right 依次反转
4. 最后将头尾对调(需要将反转部分的末尾节点与前一个节点连接起来),即 begin的下一个结点为right,left的下一个结点为end(若left为空,说明begin是头结点,即反转从头开始,则有head=end)