算法学到递归时,就算是有了一个坎,很多人迈不过去,迈不过去的原因主要是,很容易被绕进去,其主要原因是太多人想搞清楚整个递归执行的过程,而解决的办法就是跳出这种思维,不是关心递归执行的过程,而是你递归程序正确与否。用固定好的范式、形成顶层思维来解决递归问题。
    设计/理解递归程序:

    • 1、数学归纳法 -> 结构归纳法

    k(0)是正确的,假设K(i)是正确的,如果K(i+1)是正确的,则所有的K(n)都是正确的

    1. function fib(n){
    2. if(n<=2)
    3. return n;
    4. return fib(n-1) + fib(n-2)
    5. }

    在上面最基础的斐波那契数列中,不要关注递归执行的过程,而只关注归纳是否正确。

    • 2、赋予递归函数一个明确的意义

    fib(n)代表的是第n项斐波那契数列的值

    • 3、思考边界条件

    n<=2即为边界条件

    • 4、实现递归过程

    写步骤1中推理出的递归函数
    因此,按着上面范式,碰到一个题目,先按着步骤1推理是否适合递归,接着三步编码实现:函数意义、边界条件、递归过程。
    eg1:二叉树的前序遍历:
    1、函数意义:前序遍历以root为根节点的二叉树
    2、边界条件:root为空是不需要遍历
    3、递归过程:前序遍历左子树、前序遍历右子树

    1. var preorderTraversal = function (root) {
    2. //前序遍历以root为根节点的二叉树
    3. const traversal = (root, res) => {
    4. //边界条件
    5. if (!root) {
    6. return;
    7. }
    8. res.push(root.val);
    9. //递归过程
    10. traversal(root.left, res);
    11. traversal(root.right, res)
    12. }
    13. let res = [];
    14. traversal(root, res)
    15. return res;
    16. };

    eg2:二叉树的最大深度
    1、函数意义: 传入根节点,获取最大深度
    2、边界条件:root
    3、递归过程:

    1. var maxDepth = function (root) {
    2. if (!root) return 0;
    3. const left = maxDepth(root.left);
    4. const right = maxDepth(root.right);
    5. return Math.max(left, right) + 1;
    6. };