老规矩先上本方法,要求一遍遍历,所以先设置一个备用链表。找到起始位置后,新增结点,并使每一个新增结点的next设置为上次的结点,记录反转的开始前位置和结束后位置,反转区间结束后,是前位置链接到临时链表开头,临时链表的结尾和没有原链表后面接上。为了涵盖从1开始的情况,所以备用链表从空节点0开始,故而返回的时候返回chead->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:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(head==nullptr||m==n)
return head;
ListNode *chead=new ListNode();
ListNode *cpmove=chead;
int i=1;
while(i!=m)
{
cpmove->next=head;
head=head->next;
cpmove=cpmove->next;
i++;
}
ListNode *temp=new ListNode(head->val);
head=head->next;
ListNode *tempend=temp;
for(i=m+1;i<=n;i++)
{
ListNode *p1=new ListNode(head->val);
p1->next=temp;
temp=p1;
head=head->next;
}
cpmove->next=temp;
tempend->next=head;
return chead->next;
}
};
上面的方法是申请了新空间,把原链表的值复制过来形成新结点,想了一下,可以直接使用原结点来反转
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(head==nullptr||m==n)
return head;
//记录反转前的位置,因为可能从1开始,所以必须设置一个新的head
ListNode *chead=new ListNode();
ListNode *cfront=chead;//记录反转序列前的最后一个结点
int i=0;
//开始反转
while(i!=m-1)
{
cfront->next=head;
cfront=cfront->next;
head=head->next;
i++;
}
//找到反转起点
ListNode *cend=head;//需要记录反转的起点作为终点
ListNode *crbegin=head;//需要记录反转的头结点
head=head->next;
//开始反转
for(i=m+1;i<=n;i++)
{
cfront->next=head;//将反转的结点挂到最前面
head=head->next;//原链表更新
cfront->next->next=crbegin;//和已反转的序列拼接
crbegin=cfront->next;//更新反转的头结点
}
cend->next=head;//拼接后面未反转的
return chead->next;//注意返回值
}
};