JavaScript数据结构与算法 - 递归
Posted 友人A ㅤ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript数据结构与算法 - 递归相关的知识,希望对你有一定的参考价值。
1. 递归
递归是一种解决问题的方法,从解决问题的各小部分开始,直到解决最大的问题,涉及函数调用自身。能使操作树和图数据结构更简单。
直接调用自身的函数或方法:
function recursiveFunction(someParam) {
recursiveFunction(someParam);
}
间接调用自身的函数:
function recursiveFunction1(someParam) {
recursiveFunction2(someParam);
}
function recursiveFunction2(someParam) {
recursiveFunction1(someParam);
}
如果执行recursiveFunction,结果是它会一直执行下去。因此,每个递归函数都必须有基线条件,即一个不再递归调用的条件(停止点),以防止无限递归。
2. 计算阶乘
2.1 迭代阶乘
(n) * (n -1) * (n-2) * (n -3) * … * 1
function factorialIterative(number) {
if (number < 0) return undefined;
let total = 1;
for (let n = numbe; n > 1; n--) {
total = total * n;
}
return total;
}
console.log(factorialIterative(5));
2.2 递归阶乘
function factorial(n) {
// 基线条件
if (n === 1 || n === 0) {
return 1;
}
// 递归调用
return n * factorial(n - 1);
}
console.log(factorial(5));
- 递归时,每个函数调用会堆叠在调用栈的顶部,这是因为每个调用都可能依赖前一个调用的结果。
- 如果递没有基线条件,递归也不会无限执行下去,浏览器会抛出错误,也就是栈溢出错误,因为每个浏览器都有自己的浏览上限。
3. 斐波那契数列
斐波那契数列是一个由 0、1、1、2、3、5、8、13、21、34 等数组成的序列。
3.1 迭代
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;
}
3.2 递归
function fibonacci(n) {
// 基线条件
if (n < 1) return 0;
if (n <= 2) return 1;
// 计算n > 2的斐波那契数的逻辑
return fibonacci(n - 1) + fibonacci(n - 2);
}
3.3 记忆化斐波那契数
记忆化是一种保存前一个结果的值的优化技术,类似于缓存。
function fibonacciMemoization(n) {
// 声明一个memo数组来缓存所有的计算结果
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;
}
递归和迭代的对比:
- 迭代比递归快很多
- 递归更容易理解,需要的代码通常也更少
- 对一些算法来说,迭代的解法可能不可用,而且有了尾调用优化,递归的多余消耗甚至可能被消除
以上是关于JavaScript数据结构与算法 - 递归的主要内容,如果未能解决你的问题,请参考以下文章