Dynamic Programming
动态规划定义
动态规划主要是对普通递归的一种优化。每当我们看到递归解决方案对相同输入进行了重复调用时,我们就可以使用动态规划来优化它。这个想法是简单地存储子问题的结果,这样当后续需要时就不必重新计算它们。这种简单的优化通常将时间复杂度从指数型减少到多项式型。
如何工作的
- 识别子问题:将主要问题划分为更小的独立子问题。
- 存储解决方案:解决每个子问题,并将解决方案存储在表格或数组中。
- 构建解决方案:利用存储的解决方案构建主要问题的解决方案。
- 避免冗余:通过存储解决方案,动态规划确保每个子问题只解决一次,从而减少计算时间。
从爬楼梯问题开始
当我们在爬楼梯时,假设每层楼有 n
级台阶,那么我们每次可以爬 1 级或 2 级台阶。那么我们爬到第 n
级台阶有多少种方法呢?
比如我们有 10 级台阶
0-1 1种(1步) 0-2 2种(1步+1步,2步) 0-3 3种(1步+1步+1步,1步+2步,2步+1步) 0-4 5种(1步+1步+1步+1步,1步+1步+2步,1步+2步+1步,2步+1步+1步,2步+2步) …
我们可以发现一个规律,那就是 f(n) = f(n-1) + f(n-2)
,这就是一个典型的动态规划问题。
因此,我们可以写出递归公式:
f(n) = f(n-1) + f(n-2)
现在我们用动态规划来解决一个求n个台阶有多少种走法的问题。
如果用普通递归,不进行DP优化的方式来解决这个问题,那么时间复杂度是指数级的,因为每次递归都会产生两个子问题,而每个子问题又会递归产生两个子问题,以此类推。 颜色相同的节点表示相同的子问题,因此存在大量冗余计算。