前言>写此文章的主旨中心是为了给阅读的同学提供一个只有干货+实战的心得体会, 方便没有自己的学习路线的同学能够快速了解一些问题的核心以及解决问题的思路.
当然了这些内容也不是自己思考出来的,也是通过学习别人的内容总结归纳出来的,所以对于博主来说也是一个学习成长以及记录的过程, 有一些不足之处还请谅解, 希望大家都能共同进步, 汲取更多的知识, 早日找到中意的工作~
链表作为一种特别的基础数据类型结构, 因其存在了next指针, 使得我们可以兼顾迭代或者递归的两种方式处理链表用来解决常用的问题
关于递归与迭代的区别, 我们可以简单的理解为:
迭代: 通过for循环的方式, 找到需要处理的节点, 进行处理
递归: 通过不断调用递归函数方式, 达成需要的操作.
通常情况下, 迭代比递归更加容易理解, 且递归在复杂程度高的基础上, 空间复杂度也相对较高一些, 因此建议常规使用迭代.
本文我们都会描述一下两种情况的使用 便于对比区别
leetcode 206 反转链表:
迭代法的核心: 需要使用一个辅助节点, 用来方便进行指针的方向转换
代码如下:
递归法的核心: 主要理解递归函数的核心意义所在, 将复杂问题抽象成简单的情况, 比如当前的反转问题
我们把当前函数reverse 定义为 反转以head节点为头节点的整个链表
比如1->2->3->4->5 开始进入则变为 1 -> reverse(2->3->4->5) 逐层递进
根据reverse函数的定义 假设后面已经转换完成到最外层时 则变成了 1->2<-3<-4<-5 并且此时返回的节点为5 即反转后的头节点
此时head为1 那么我们需要做的就是改变节点1.next的指向 与 2.next的指向
代码如下:
依据上面一题我们可以较为清晰的看到 迭代与递归的两种解题方式的思路差别, 也有一些基于以上基础问题的升级问题, 下面我们也列出来看一看
先看递归的升级版本 leetcode: 92反转链表
解题思路仍然是要拆分子问题, 首先明确主函数的定义: 给定head 反转其中 left 到 right的节点, 其他节点不动
我们可以很容易想到 当left = 1时, 就相当于反转前right个节点
那么我们可以首先定义一个函数 reverse(ListNode head, int n) 用来反转head为节点的头结点的前n个节点, 并返回反转后的头节点.
然后依次向前寻找到达该节点的位置 即对于left到right间, 当我们left向前移动到left.next时, 此时应该反转的节点个数即 right - 1个了
所以有如下代码:
比如迭代的升级版本: leetcode 25 K个一组翻转链表
该问题放在最后, 是因为在解决思路的考虑中, 我们兼顾了迭代与递归的思想策略
比如对于节点a, 向后k个节点为b 时 我们可以通过迭代的方式快速翻转此部分链表, 并返回反转后的头节点
但是反转完成的只是一部分, 对于后续的节点我们仍然要继续反转, 而后续这一部分也与之前一致的思路, 此处就体现了递归的思想,
代码如下: