引入
动态规划问题(Dynamic Programming)应该是很多人头疼的一类问题,
本文尝试探索一种套路帮助解决此类问题
什么是动态规划?
动态规划的核心思想是将问题分解为一系列子问题,并通过记忆化或递推的方式求解子问题,从而得到原始问题的解。
动态规划的特点
其主要特点包括:
- 重叠子问题:问题的解能够通过多次重复计算相同的子问题得到。
- 最优子结构:问题的最优解能够由子问题的最优解推导得出。
解题办法
动态规划通常分为自顶向下的记忆化搜索和自底向上的递推两种方法。
解题套路框架
解决动态规划问题通常遵循以下套路框架:
递归的暴力解法 -> 带备忘录的递归解法 -> 非递归的动态规划解法。这个过程是层层递进的解决问题的过程,
具体的过程
-
确定状态
需要明确问题的状态是什么,以及在状态转移过程中如何更新状态。 -
定义状态转移方程
状态转移方程描述了状态之间的转移关系。它明确了如何从已知的状态计算出未知状态的值。 -
处理边界条件
边界条件是指状态转移的起点或终点,通常需要单独考虑和处理。 -
计算动态规划数组
使用循环遍历计算动态规划数组中的每个元素,根据状态转移方程填充数组。 -
返回结果
根据问题的具体要求,从动态规划数组中选取相应的值作为最终的结果。
举例说明
以下是一个使用动态规划解决斐波那契数列问题的示例:
斐波那契数列
题目描述
斐波那契数列是一个非常经典的数列,它的第一个和第二个数分别为 0 和 1,从第三个数开始,每个数都是前两个数之和。即斐波那契数列的定义如下:
F(0) = 0,
F(1) = 1,
F(n) = F(n-1) + F(n-2) (n >= 2)
给定一个整数 n,编写一个函数来计算斐波那契数列中第 n 个数的值。
例如:
输入:n = 0,输出:0
输入:n = 1,输出:1
输入:n = 5,输出:5
输入:n = 10,输出:55
解题思路
方式一:暴力求解
以java为例
public class Fibonacci {
// 暴力递归求解斐波那契数列
public static long fibonacci(int n) {
// base case
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
// 递归计算前两个数的和
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
public static void main(String[] args) {
int n