题目链接:206. 反转链表
题目:
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
进阶:
链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
思路和算法:
方案一:迭代法思路。假设链表为 1→2→3→∅,我们想要把它改成 ∅←1←2←3。在遍历链表时,将当前节点的next 指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。
方案二:递归法思路。(算法思路来自于官方题解)
代码(C++):
方案一:迭代法
//迭代
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr; //记录head的前一个节点
while (head) {
ListNode* node = head->next; //在更改引用之前,存储后一个节点
head->next = prev;
prev = head;
head = node;
}
return prev; // 返回新的头节点(反转前链表的最后一个节点)
}
};
方案二:递归法
(1)先不写复杂的递归,将递归拆分,便于理解。
//递归
//先不写复杂的递归,将递归拆分,便于理解
class Solution {
public:
ListNode* reverse(ListNode* pre, ListNode* cur) {
if (!cur) return pre; //如果当前节点为nullptr,则返回前一个节点pre
ListNode* node = cur->next; //记录当前节点未改变引用之前的next
cur->next = pre;
return reverse(cur, node);
}
ListNode* reverseList(ListNode* head) {
return reverse(NULL, head);
}
};
(2)最终合并的递归。
最后head->next必须指向空,否则可能形成环。
//递归
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; //此时的head节点是尾节点,其next需指向nullptr
return newHead;
}
};