head,反转链表并返回反转后的链表的头节点。该题很有代表性,其可以写出原地反转链表的递归和迭代两个版本的解法。
迭代版本的解法相当于是从头到尾遍历链表并模拟断链并反转的过程。
pre、cur 和 next,其中 cur 初始化为 head,另两个指针初始化为空指针。cur 不为空,则一直进行下述操作:
next 置为 cur 的下一个节点,即 next = cur->next。【保存下一个节点,因为准备断开 cur 指向 cur->next 的链】cur 的下个节点置为 pre,即 cur->next = pre。【将 cur 的方向反转】pre 置为 cur,即 pre = cur。【pre 向后移动】cur 置为 next,即 cur = next。【cur 向后移动】pre 指针作为反转后的链表头部。第一步,保存下一个节点:

第二步,将 cur 的方向反转:

第三步,pre 向后移动:

第四步,cur 向后移动:

由前面可以看出,迭代解法相当于从前往后反转链表,而递归解法相反,是从后往前反转链表。
head 非空且 head->next 非空,如果其中一个为空则直接返回 head。【遇到链表的尾部才会在此处直接返回】head->next,并将返回结果置为 newHead。【newHead 是本次函数返回的结果,不难想象得出,函数一路递归遍历链表,最后会把链表尾部元素返回作为反转后的链表头部】head->next 的下一个节点置为 head,即 head->next->next = head。【将 head->next 的方向反转】head 的下一个节点置为空,即 head->next = nullptr。【此步较为关键,如果不置空,则会造成 cur 与 cur->next 互指的情况】newHead 指针作为反转后的链表头部。class Solution
{
public:
ListNode* reverseList(ListNode* head)
{
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* next;
while(cur)
{
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *p;
for(p=NULL; head; swap(head,p))
swap(p,head->next);
return p;
}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) {
return head;
}
ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return newHead;
}
};
class Solution
{
private:
ListNode* reverse(ListNode* pre, ListNode* cur) // 尾递归
{
if(!cur) return pre;
ListNode* next = cur->next;
cur->next = pre;
return reverse(cur, next); // 最后一步调用自身
}
public:
ListNode* reverseList(ListNode* head)
{
return reverse(nullptr, head);
}
};