爬楼梯
爬楼梯是是一个经典的动态规划问题,本文中提到了三种解决这个问题的思路,一种是通过动态规划,另一种是通过递归,还有一种是记忆法。实际上,它们这三种方法都是等价的,只是在实现方式上略有不同。
1.递归法
2.记忆法
3.动态规划
递归
递归则是一种自顶向下的思路,通过不断地将问题分解为更小的子问题来求解。它并不是一种算法,而是一种实现的方式,是内存的不断使用和函数栈的入栈。需要注意的是,递归在处理大规模问题时可能会导致栈溢出的问题,因为每次函数调用都会在栈中占据一定的空间。为了避免这个问题,可以使用尾递归优化或者迭代的方式进行实现。
在这个问题中,我们可以定义一个递归函数 climbStairs(n),表示爬到第 n 阶楼梯的不同方法数。根据题目要求,递归函数的终止条件是当 n <= 1 时,返回 1;否则,返回 climbStairs(n-1) + climbStairs(n-2)。
if(n === 1) return 1;
if(n === 2) return 2;
return climStairs(n-1)+ climStairs(n-2);
}
记忆
使用记忆法(Memoization)可以优化递归方法中的重复计算问题。记忆法通过存储已经计算过的结果,避免重复计算。
在这个问题中,我们可以创建一个字典或数组来保存已经计算过的爬楼梯的不同方法数。每次递归调用时,先检查字典或数组中是否已经存在计算结果。如果存在,则直接返回该结果;如果不存在,则进行计算,并将结果存储在字典或数组中。
const climbStairs=function(n){
//退出条件
if(n===1)return 1;
if(n===2)return 2;
if(f[n] === undefined){//第一次
//函数嵌套函数
f[n]=climbStairs(n-1)+climbStairs(n-2);//递归的公式
}
return f[n];
}
动态规划
动态规划是一种自底向上的思路,通过存储中间结果来避免重复计算。我们定义一个数组 dp,其中 dp[i] 表示爬到第 i 阶楼梯的不同方法数。然后通过状态转移方程 dp[i] = dp[i-1] + dp[i-2] 来计算 dp 数组的每个元素。
在实际应用中,动态规划通常比递归效率更高,因为动态规划利用了中间结果的存储,避免了重复计算。而递归则可能导致大量的重复计算,增加了时间和空间的开销。因此,对于这个问题,使用动态规划的方法更为推荐。
const f=[];//优化
f[1]=1;
f[2]=2;
for(let i=3;i<=n;i++){
//递推公式
f[i]=f[i-1]+f[i-2];
}
return f[n];
}