基于动态规划的思想来做题,我们首先要想到的思维工具就是“倒着分析问题”。“倒着分析问题”分两步走:
- 定位到问题的终点
- 站在终点这个视角,思考后退的可能性 像阶乘,爬楼梯这种都是很适合用动态规范的思想
爬楼梯
// javascript写法
const climbStairs = (n) => {
if (n === 1) return 1
if (n === 2) return 2
return climbStairs(n - 1) + climbStairs(n - 2)
}
const factorial = (n) => {
if (n === 1) return 1
return n * factorial(n - 1)
}
阶乘
const factorial = (n) => {
if (n === 1) return 1
return n * factorial(n - 1)
}
但是爬楼梯第一种会导致多余的开销,因为他会重复累积计算,那有没有办法只需要做到累积的值,重复的值而不需要计算呢?那通常都有一种方法,就是用空间换时间
const climbStairs = (n) =>{
const f = [];
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]
}
动态规划:
动态规划则恰恰相反,是一个自底向上的过程。它要求我们站在已知的角度,通过定位已知和未知之间的关系,一步一步向前推导,进而求解出未知的值。
在这道题中,已知 f(1) 和 f(2) 的值,要求解未知的 f(n),我们唯一的抓手就是这个等价关系:
f[n] = f[n-1] + f[n-2]
const climbStairs = (n) => {
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]
}