定义三个指针:
一个指向pre:
一个指向cur:
一个指向next:
因为反转链表后,第一个指向的下一个要为null,所以要把pre先设为null;
cur指向本节点,然后先保存下一个节点tempnext,因为如果cur的next指针要反向,反向后就找不到next节点了。然后把cur的next指向pre,pre更新为cur,cur更新为tempnext。
丑陋的代码:
ListNode* ReverseList(ListNode* pHead) {
if (pHead == nullptr)
return nullptr;
if (pHead->next == nullptr)
return pHead;
ListNode* pre=nullptr;
ListNode* cur = pHead;
ListNode* res = nullptr; //保存最后结果
while (1)
{
ListNode* tempnext = cur->next;
cur->next = pre;
if (tempnext == nullptr) //如果已经指向null了,那么就需要跳出了。
{
return res=cur;
}
pre = cur;
cur = tempnext;
}
}
但是因为有时候会要求只是反转一部分,如图
为了使得上述代码能复用,需要改动一下:
ReverseList_part 表示只是反转部分,形参表示指向反转开始的头和尾;
ListNode* ReverseList_part(ListNode* pHead, ListNode* pEnd)
{
if (pHead == nullptr)
return nullptr;
ListNode* pre = nullptr;
ListNode* cur = pHead;
ListNode* res = nullptr;
while (cur!=pEnd) //这里的end是为空或者尾节点的下一个节点
{
ListNode* tempnext = cur->next;//最后一步时,tempnext 已经指向尾部的下一个(或空)
cur->next = pre;
pre = cur; //更新pre为cur (此时pre为最后一个节点)
cur = tempnext; //cur等于空或者尾节点下一个,下一步跳出循环
}
return pre; //pre就是所求
}
上述代码的结果仅适用于截取一部分反转,我想着把这个稍微改一下用到那个例子中,但发现不行。。。主要是要记录两个指针的同时还要分别记录pHead的前一个和pEnd的后一个,还有当m=1时的特殊情况。。
下面是原题的代码:
ListNode *reverseBetween(ListNode *head, int m, int n)
{
ListNode *addPreHead=new ListNode(-1); //新建一个头-头指针,比head还在前面
addPreHead->next = head;
ListNode *reshead = addPreHead;
for (int j = 0; j < m-1;j++)
{
addPreHead = addPreHead->next; //找到反转的前一个节点
}
ListNode* pre = nullptr; //表示前一个节点
ListNode* cur = addPreHead->next; //表示当前节点
ListNode* tail = cur; //表示当前节点主要是方便最后把他的next指向反转部分的下一个节点
for (int i = m; i <= n;i++)
{
ListNode* tempnext = cur->next;
cur->next = pre;
pre = cur;
cur = tempnext;
}
addPreHead->next = pre; //前一个节点指向反转后的链表头节点
tail->next = cur; //链接后一个节点
return reshead->next; //返回头指针
}