动态规划问题 (dynamic programming)的总结

本文深入浅出地介绍了动态规划的基本概念及其与回溯法的区别,通过斐波那契数列等经典实例阐述了如何定义中间状态及寻找状态转移方程,并列举了一系列常见的动态规划问题。

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

相比于链表,字符串,或者暴力的直接回溯问题,动态规划问题是有难度的。它的难点在于不像前面的问题那么直接,

需要我们自己去寻找规律。这个规律也就是问题如何拆分的规律。往往我们为了求解当前的状态,找到它跟前面的状态的联系,借助于前面的状态,快速地求解得到当前的状态。

下面我将从简单的动态规划实例,动态规划与回溯的区别,典型的动态规划这几个方面来讲解。

1. 简单的动态规划实例

我们来看一下斐波那契问题。比如我们需要计算前 n 个斐波那契数。

我们当计算到第 i 个 值的时候,我们知道F ( i ) = F ( i - 1 ) + F ( i -  2 )。

如果我们之前已经存储下来 F ( i - 1 ) 和 F ( i - 2 ) 的值,我们是不是就能够很轻松地计算出F ( i )了?

要是没有存储的,我们需要将 F ( i - 1)继续展开成 F ( i - 2 ) + F ( i - 3 ),直到到达 F ( 0 )或者 F ( 1 )。

(如果不存储,计算 F ( n ) 的复杂度将会是将会随 n 指数增长 ,存储的话,计算复杂度为O ( n ),  差别是多么大啊! )

在这里, F ( i ) 中间状态。F ( i ) = F ( i - 1 ) + F ( i -  2 ) 为我们的转移矩阵

很多时候动态规划的难点在于如何定义中间状态和寻找转移矩阵。

2. 动态规划与回溯的区别

动态规划跟回溯很像,就是将大问题问题拆分成小问题的思想。

一般而言,如果要找出所有符合的结果,这时候就应该回溯。

如果是需要找出最大的,最小的这类,就该用动态规划了。

3. 典型的动态规划

比如换零钱问题, 给出各种面值的零钱array,和一个总数目 n ,找到最小零钱个数的兑换。

在这里,中间状态可以表示总的钱的数目为  i 的最小兑换,

状态转移矩阵为 F ( i ) = min ( F ( i - array [ 0 ] ) ,  F ( i -  array [ 1 ] ) , ... ,F ( i -  array [ array.lenght -  ] ) ) + 1;

又比如找到乘积最大的拆分,将正整数 n 进行拆分成更小的正整数,使得这些拆分的数的乘积最大。

在这里,中间状态为整数  i 进行拆分,得到的最大面积,

状态转移矩阵为 F ( i ) = max ( 1 * ( max ( i - 1, F ( i - 1 ) , ... ,  F ( i - j ) ,2 * ( max ( i - j, F ( i - j ) + ...

                                       + F ( i - i / 2 ) ,i / 2* ( max ( i - i / 2, F ( i - i / 2 ) ;

中间的max是可以选择拆分也可以选择不拆分。

比如Longest Increaing Subsequence, 要找数组中的最长递增子序列。

在这里,中间状态可以表示下标为 i 的时候,能达到的最大递增序列,

状态转移矩阵为 F ( i ) = max ( 1,cache [ j ] + 1 ) 其中 j < i, 且满足 A [ j ] < A[ i ]

其他的动态规划问题还有:

1. Minimum Path Sum 最小值的路径

2. Unique Paths 寻找从起点到终点的路径个数

3. Unique Paths II 带有障碍的网格中起点到终点的个数

4. Triangle 三角形中的最短路径

5. Climbing Stairs 爬楼梯的选择

6. House Robber 如何获得最大的钱

7. Best Time to Buy and Sell Stock 买卖股票的最好时间

8. Maximum Subarray 和最大的子数组

9. Maximum Product Subarray 乘积最大的子数组

10. Range Sum Query - Immutable 一段范围内的值查询

11. Range Sum Query 2D - Immutable 计算矩形中的元素和

12. Counting Bits 计算二进制形式中的1的个数

13. Decode Ways 不同的解码可能性

14. Perfect Squares 平方数的组合Integer Break 找到乘积最大的拆分

15. Word Break 单词分割

16. Word Break II 单词分割系列2

17. Longest Valid Parentheses 最长的合法括号序列

18. Distinct Subsequences 不同的子序列个数

总结:

解动态规划的问题的关键在于找出当前的状态怎么借助之前的状态得到

为了更好地掌握,需要思考,并且练习,并且总结。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值