递归-206.反转链表-力扣(LeetCode)

个人主页1白天的黑夜1-CSDN博客

专栏:力扣刷题录_1白天的黑夜1的博客-CSDN博客企鹅程序员:Linux 系统与网络编程_1白天的黑夜1的博客-CSDN博客

目录

一、题目解析

[1、链表中节点的数目范围是 [0, 5000]](#1、链表中节点的数目范围是 [0, 5000])

[2、-5000 <= Node.val <= 5000](#2、-5000 <= Node.val <= 5000)

二、算法原理

解法:递归

视角1:从宏观角度看待问题

即需经过三个阶段:

1、先将当节点后面的链表反转,返回一个新的头节点

2、将当前节点链接到反转的链表后

3、最后将当前节点的next置空

视角2:将链表看成一颗树,对其进行一次后序遍历

边界情况:先遍历到最后,如果节点为空,返回nullptr;如果节点的next为空,则返回节点本身。

根据返回的新头节点,将链表反转。

第一步,先通过head的next找到返回的新头节点,也就是图中值为5的节点,然后让它的next指向head也就是值为4的节点;

第二步,将head的next改为nullptr,完成反转,然后继续向上返回。

总结一下:两种视角虽不同,但最后写出来的代码都是一样。如果对于宏观视角理解起来困难的读者,可以看一看第二种视角,把链表看作一颗树。

如何编写递归代码?

1、重复的子问题->函数头设计

2、只关心某一个子问题做的什么->函数体设计

3、递归函数的出口

结合两种视角和自己的思路,可以先去尝试一下编写代码,来提升自己的代码水平,题目链接如下

三、代码示例

四、递归展开图

看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!


一、题目解析

1、链表中节点的数目范围是 [0, 5000]

2、-5000 <= Node.val <= 5000

二、算法原理

相信各位读者在学习链表这个数据结构的时候,已经学会了通过迭代(循环)的方式解决链表的反转,本篇博客如标题所示将会带来递归的解法,话不多说开始进入正文。

解法:递归

视角1:从宏观角度看待问题

为了方便更改改链接的指向,我们期望的是将头指针后的n-1个节点先反转,然后返回一个反转后的头指针,在剩下的n-1个节点,对于第二个节点,自然期望后n-2个节点先反转,然后返回一个头指针,一直这样递归下去,直到节点为空或者节点的next为空,即没有节点了和只有一个节点的情况,直接返回nullptr或节点本身,此时可以开始链接了。以最后一次更改举例,此时后n-1个节点反转后返回了新的头节点newhead,此时n-1个节点反转后的最后一个节点是第二个节点,通过head的next可以找到,让第二个节点的next指向head,使head称为新的尾节点,然后将head的next改为nullptr,返回新的头节点newhead,完成链表的反转。

即需经过三个阶段:
1、先将当节点后面的链表反转,返回一个新的头节点
2、将当前节点链接到反转的链表后
3、最后将当前节点的next置空

视角2:将链表看成一颗树,对其进行一次后序遍历

链表可以看作一棵特殊的树,将横着摆放的链表竖直摆放,此时再看就有点树的感觉了。后序遍历是一种二叉树的遍历方法,即先左子树、右子树、根的顺序遍历二叉树,与其相似的还有前序遍历和中序遍历,它们的区别在于根访问的位置,第一个就访问的根就是前序遍历,在中间就是中序遍历,在最后就是后序遍历。接下来看一看具体过程。

边界情况:先遍历到最后,如果节点为空,返回nullptr;如果节点的next为空,则返回节点本身。
根据返回的新头节点,将链表反转。
第一步,先通过head的next找到返回的新头节点,也就是图中值为5的节点,然后让它的next指向head也就是值为4的节点;
第二步,将head的next改为nullptr,完成反转,然后继续向上返回。

总结一下:两种视角虽不同,但最后写出来的代码都是一样。如果对于宏观视角理解起来困难的读者,可以看一看第二种视角,把链表看作一颗树。

如何编写递归代码?

1、重复的子问题->函数头设计

我们的重复子问题是,将当前节点后面的链表反转,所以需要一个ListNode*类型的变量。由于我们还需要返回新的头指针,所以返回值类型也是ListNode*。题目给我们提供的函数就可以拿过来直接用。

2、只关心某一个子问题做的什么->函数体设计

在链接当前指针和后面反转后的链表的操作,就是我们函数体内的内容。先用一个ListNode*类型的变量newhead接受递归函数的返回值,然后进行指针的修改,把当前节点链接到最后,并将其置空,最后返回newhead即可。

3、递归函数的出口

如果一个递归函数没有出口,会导致函数一直递归,导致栈溢出。经过上面的分析,当节点为空时,直接返回nullptr;如果节点的next为空,则返回节点本身。

结合两种视角和自己的思路,可以先去尝试一下编写代码,来提升自己的代码水平,题目链接如下

206. 反转链表 - 力扣(LeetCode)

三、代码示例

cpp 复制代码
class Solution {
public:
    //递归
    ListNode* reverseList(ListNode* head)
    {
        if(head == nullptr) return nullptr;
        if(head->next == nullptr) return head;
        ListNode* newhead = nullptr;
        newhead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newhead;
    }
};

四、递归展开图

为了避免过于复杂(其实是博主懒画这么多递归展开图),使用1->2->3->nullptr为例子。

通过递归展开图,我们可以肯定递归函数能帮我们完成工作,所以我们要相信递归函数。

看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!

相关推荐
靠近彗星3 小时前
3.1 栈
数据结构·算法
Fcy6483 小时前
C++ vector容器的解析和使用
开发语言·c++·vector
无限进步_4 小时前
C语言文件操作全面解析:从基础概念到高级应用
c语言·开发语言·c++·后端·visual studio
_OP_CHEN4 小时前
C++基础:(十五)queue的深度解析和模拟实现
开发语言·c++·stl·bfs·queue·容器适配器·queue模拟实现
sulikey4 小时前
一文彻底理解:如何判断单链表是否成环(含原理推导与环入口推算)
c++·算法·leetcode·链表·floyd·快慢指针·floyd判圈算法
Swift社区4 小时前
LeetCode 402 - 移掉 K 位数字
算法·leetcode·职场和发展
起床气2334 小时前
C++海战棋开发日记(序)
开发语言·c++