算法学到递归时,就算是有了一个坎,很多人迈不过去,迈不过去的原因主要是,很容易被绕进去,其主要原因是太多人想搞清楚整个递归执行的过程,而解决的办法就是跳出这种思维,不是关心递归执行的过程,而是你递归程序正确与否。用固定好的范式、形成顶层思维来解决递归问题。
设计/理解递归程序:
- 1、数学归纳法 -> 结构归纳法
k(0)是正确的,假设K(i)是正确的,如果K(i+1)是正确的,则所有的K(n)都是正确的
function fib(n){if(n<=2)return n;return fib(n-1) + fib(n-2)}
在上面最基础的斐波那契数列中,不要关注递归执行的过程,而只关注归纳是否正确。
- 2、赋予递归函数一个明确的意义
fib(n)代表的是第n项斐波那契数列的值
- 3、思考边界条件
n<=2即为边界条件
- 4、实现递归过程
写步骤1中推理出的递归函数
因此,按着上面范式,碰到一个题目,先按着步骤1推理是否适合递归,接着三步编码实现:函数意义、边界条件、递归过程。
eg1:二叉树的前序遍历:
1、函数意义:前序遍历以root为根节点的二叉树
2、边界条件:root为空是不需要遍历
3、递归过程:前序遍历左子树、前序遍历右子树
var preorderTraversal = function (root) {//前序遍历以root为根节点的二叉树const traversal = (root, res) => {//边界条件if (!root) {return;}res.push(root.val);//递归过程traversal(root.left, res);traversal(root.right, res)}let res = [];traversal(root, res)return res;};
eg2:二叉树的最大深度
1、函数意义: 传入根节点,获取最大深度
2、边界条件:root
3、递归过程:
var maxDepth = function (root) {if (!root) return 0;const left = maxDepth(root.left);const right = maxDepth(root.right);return Math.max(left, right) + 1;};
