1. 什么是递归
递归是一种解决问题的方法,它从解决问题的各个小部分开始,直到解决最初的大问题。递归通常涉及函数调用自身
递归代码模版
recursion(level, param1, param2, ...) {
// 递归终止条件
if (level > MAX_LEVEL) {
return
}
// 处理当前层逻辑
process(level, data...)
// 下探到下一层
recursion(level + 1, p1, ...)
// 如果需要,清理当前层
}
2. 计算阶乘
使用循环
function factorialIterative(number) {
if (number < 0) return undefined;
let total = 1;
for (let n = number; n > 1; n--) {
total = total * n;
}
return total;
}
使用递归
function factorial(n) {
if (n === 1 || n === 0) { // 基线条件
return 1;
}
return n * factorial(n - 1); // 递归调用
}
3. 斐波那契数列
- 位置 0 的斐波那契数是零。
- 1 和 2 的斐波那契数是 1。
- n(此处 n > 2)的斐波那契数是(n - 1)的斐波那契数加上(n - 2)的斐波那契数
- 迭代法
function fibonacciIterative(n) {
if (n < 1) return 0;
if (n <= 2) return 1;
let fibNMinus2 = 0;
let fibNMinus1 = 1;
let fibN = n;
for (let i = 2; i <= n; i++) {
fibN = fibNMinus1 + fibNMinus2;
fibNMinus2 = fibNMinus1;
fibNMinus1 = fibN;
}
return fibN;
}
- 递归法
function fibonacci(n){
if (n < 1) return 0;
if (n <= 2) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
以上代码执行情况
添加缓存
function fibonacciMemoization(n) {
const memo = [0, 1];
const fibonacci = (n) => {
if (memo[n] != null) return memo[n];
return memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);
};
return fibonacci;
}
4. 为什么使用递归
迭代的版本比递归的版本快很多,所以这表示递归更慢。但是,递归版本更容易理解,需要的代码通常也更少。另外,对一些算法来说,迭代的解法可能不可用,而且有了尾调用优化,递归的多余消耗甚至可能被消除
它来解决问题会更简单
如何优雅地计算斐波那契数列 time.geekbang.org/dailylesson…
5. 实战题目
5.1 easy
1.爬楼梯
难度:简单
2.翻转二叉树
难度:简单
题解:翻转二叉树(递归与迭代)
3.二叉树的最大深度
难度:简单
题解:二叉树的最大深度 DFS
4.二叉树的最小深度
难度:简单
题解:二叉树的最小深度 BFS
5.二叉树的最近公共祖先
难度:简单
题解:二叉树的最近公共祖先
5.2 medium
1.括号生成
难度:中等
2.验证二叉搜索树
难度:中等
3.从前序与中序遍历序列构造二叉树
难度:中等
4.组合
难度:中等
5.全排列
难度:中等
题解:全排列(回溯)
6.全排列 II
难度:中等
5.3 hard
1.二叉树的序列化与反序列化
难度:困难