递归 & 尾递归
machao07 opened this issue · comments
一、递归
递归的特点
- 自身调用:原问题可以分解为子问题,子问题和原问题的求解方法是一致的,即都是调用自身的同一个函数
- 终止条件:递归必须有一个终止的条件,即不能无限循环地调用本身
实现从1到n的累加
function sum(n) {
if (n === 1) return n;
return sum(n - 1) + n
}
sum(5) // 15
分析
- sum(5)时,先sum(5)入栈,然后原问题sum(5)拆分为子问题sum(4),再入栈,直到终止条件sum(n=1)=1,就开始出栈
- sum(1)出栈后,sum(2)开始出栈,接着sum(3)
- sum(1)就是后进先出,sum(5)是先进后出,递归过程可以理解为栈出入过程
递归解题思路
- 定义函数功能
- 寻找递归终止条件
- 递推函数的等价关系式
例阶乘
function factorial(n) {
if (n === 1) return 1;
return n * factorial(n - 1)
}
factorial(5) // 120
// =>
5 * factorial(4)
5 * (4 * factorial(3))
5 * (4 * (3 * factorial(2)))
5 * (4 * (3 * (2 * factorial(1))))
5 * (4 * (3 * (2 * 1)))
5 * (4 * (3 * 2))
5 * (4 * 6)
5 * 24
120
二、尾递归
尾递归的特点
- 在尾部调用的是函数自身
- 可通过优化,使得计算仅占用常量栈空间
function factorial(n, total) {
if (n === 1) return total
return factorial(n - 1, n * total)
}
factorial(5, 1) // 120
// =>
factorial(4, 5) // 5*1
factorial(3, 20) // 4*5
factorial(2, 60) // 3*20
factorial(1, 120) // 2*60