来源于「Krahets」的《图解算法数据结构》
https://leetcode.cn/leetbook/detail/illustration-of-algorithm/
链表反转的递归要点
- 递归终止条件为当前节点为空,表明遍历到了链表尾部
- 递归函数传入参数为当前节点的下一个节点
- 按照是否重新开辟存储空间分类
- 下面只写了递归做法,遍历做法略
单指针
- 如果重新开辟空间存储反转后的链表,则只需要一个指针:即递归到表尾然后函数返回后依次存入新的空间
void reverse(vector<int>& reversedList, ListNode* node)
{if(!node) return;reverse(reversedList, node->next);reversedList.push_back(node->val);
}class Solution {
public:vector<int> reverseBookList(ListNode* head) {vector<int> reversedList;reverse(reversedList, head);return reversedList;}
};
双指针
- 如果在原地反转,则需要两个指针,一个为指向当前节点 cur,另一个指向当前节点的前一个节点 pre
- 当 cur 为空节点时,此时 pre 为链表的最后一个节点,返回 pre 作为表头
- 传参时,cur 传入 cur->next,pre 传入 cur
- 每次都接收返回的结果,但这个结果一直是最后一个节点不变
- 遍历逐层返回时进行指针的指向修改,也就是 cur->next = pre
class Solution {
public:ListNode* reverseList(ListNode* cur, ListNode* pre){//当前节点为最后一个节点的下一个节点时,将最后一个节点作为链表头返回if(!cur) return pre;ListNode* res = reverseList(cur->next, cur);cur->next = pre;return res;}ListNode* trainningPlan(ListNode* head) {return reverseList(head, nullptr);}
};