【算法-动态规划】通用模板

本文详细介绍了动态规划的概念,包括状态定义、状态转移方程的建立、遍历顺序、初始化、结果输出,以及空间优化和递归与迭代实现的选择。以爬楼梯问题为例,展示了如何应用动态规划解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、动态规划是什么?

二、通用思路

2-1、状态的定义

2-2、状态转移方程

2-3、遍历顺序

2-4、初始化

2-5、结果输出

2-6、优化

2-6-1 空间的优化

2-6-2 递归实现VS迭代实现(数组存储)


一、动态规划是什么?

动态规划(DP),即将问题不断转化为子问题,再通过子问题的求解,解决问题。

如下:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

经过分析,可以得到 F(n)=F(n-1)+F(n-2) 这个我们称之为状态转移方程

即,楼顶有n个台阶,每次可以爬1个或2个,问题可以转化为 n-1个台阶的不同方法(对应下一步爬1个台阶),加上n-2个台阶的不同方法(对应下一步爬2个台阶)。

当只有0个台阶,那么只有0中方法,即F(0)=0

当只有1个台阶,那么只有1种方法,即F(1)=1

当只有2个台阶,那么只有2种方法,即F(2)=2

当只有3个台阶,那么只有F(3)=F(2)+F(1)=2+1=3 

当有n个台阶,那么有F(n)=F(n-1+F(n-2) 种走法。

可以发现,除了0个台阶,其它的都符合我们的推理。

动态规划的难点在于,如何找出状态转移方程,当找到状态转移方程,问题迎刃而解。

因为F(n)依赖于F(n-1)和F(n-2) 所以我们必须将F(n-1)和F(n-2)的值存储下来,常用的方式是定义一个数组,如

int[] dp =new int[n+1];

二、通用思路

下面以上面的题目,尝试将动态规划的步骤拆解

2-1、状态的定义

dp[i] 为 i 个台阶,一共有多少种走法

2-2、状态转移方程

根据上面,状态转移方程为 dp[i]=dp[i-1]+dp[i-2]

2-3、遍历顺序

可以看到,对于 i 依赖于 i-1 和 i-2 ,即前面2个值

所以是后面依赖前面,顺序应该是正序

2-4、初始化

正序遍历,且需要前2个值,初始化dp数组,至少需要两个值,dp[0]为特殊情况,单独处理,所以我们至少需要提前设置

dp[1]=1;
dp[2]=2;

2-5、结果输出

对于n个台阶的最大走法,结果显然为 dp[n]

2-6、优化

2-6-1 空间的优化

可以看到,上述问题使用了一个dp数组,但是实际使用中,我们只需要2个变量就可以替代掉数组的作用,即空间上可以把O(n) 优化为O(1)

实际操作中,01背包问题,经常会通过二维的dp数组,压缩为一维的dp数组

注意事项:优化空间的过程,不能导致状态值的丢失。

2-6-2 递归实现VS迭代实现(数组存储)

既然是问题转化为子问题求解,显然递归是一个好方式,但是受限于栈的大小以及可开辟的缓存空间,可灵活考虑是使用递归实现,还是迭代实现。

如LeetCode上的一些题目,使用递归,会栈溢出,就只能使用迭代实现,另一些题目,要求空间复杂度在O(1),可考虑递归实现。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值