news 2026/8/13 4:53:26

动态规划的入门解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
动态规划的入门解析

动态规划 = 把大问题拆成小问题 + 记住小问题的答案 + 避免重复计算

最简单的题目示例——斐波那契数列
class Solution: def fib(self, n: int) -> int: # 排除 Corner Case if n == 0: return 0 # 创建 dp table dp = [0] * (n + 1) ​ # 初始化 dp 数组 dp[0] = 0 dp[1] = 1 ​ # 遍历顺序: 由前向后。因为后面要用到前面的状态 for i in range(2, n + 1): ​ # 确定递归公式/状态转移公式 dp[i] = dp[i - 1] + dp[i - 2] # 返回答案 return dp[n]
//非压缩状态的版本 class Solution { public int fib(int n) { if (n <= 1) return n; int[] dp = new int[n + 1]; dp[0] = 0; dp[1] = 1; for (int index = 2; index <= n; index++){ dp[index] = dp[index - 1] + dp[index - 2]; } return dp[n]; } }

2、动态规划的解题步骤------以上题为例

1、确定dp数组(dp table)以及下标的含义

dp[i]就是每一项的具体值——例如dp[0]的值是0,dp[1]的值是1

2、确定递推公式

本题中递推公式已经给出状态转移方程 dp[i] = dp[i - 1] + dp[i - 2];简单的题目可能会直接给出递推公式,较难的题目需要自己根据数学知识推导出来,

3、dp数组如何初始化

本题中也将初始化值给出,

dp[0] = 0; dp[1] = 1;
4、确定遍历顺序

遍历顺序根据题目进行推导,从公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,斐波那契数列是前两个数相加的结果赋值给后边的数所以dp[i]是依赖 dp[i - 1] 和 dp[i - 2],那么遍历的顺序一定是从前向后遍历的,也就可以简单的按顺序遍历的方法进行遍历,不同的题目可能也会有不同的遍历顺序。

5、举例推导dp数组

举例推导就是自己根据已经找到的规律写一些数值,然后设置n的值进行遍历看看是否和推导的结果相同,因为一般数学推导的前几个数值都是对的,那么当打印的结果不对时就打印dp数组如果发现和推导的数值不相同,就需要更改递推公式,或者找其他的代码错误。

3、较难的题目进行强化

1、确定dp数组(dp table)以及下标的含义

dp[i] [j] :表示从(0 ,0)出发,到(i, j) 有dp[i] [j]条不同的路径。最后返回的dp[i] [j]就是所有不同的路径

2、确定递推公式

对于dp[i] [j]来说dp[i] [j]=dp[i-1] [j] + dp[i] [j-1]就只有这两种情况,所以这就是dp数组的递推公式

3、dp数组如何初始化

直接从最起始的位置可以看出从(0, 0)的位置到(i, 0)的路径只有一条

所以初始化代码为: ​ for (int i = 0; i < m; i++) dp[i][0] = 1; for (int j = 0; j < n; j++) dp[0][j] = 1;
4、确定遍历顺序

根据递推公式和题目可以看出来递推之后的值是从上一个值向下或者向右推导的,所以遍历顺序就是从左到右的遍历顺序

5、举例推导dp数组

举例推导就是自己根据已经找到的规律写一些数值,根据数学等方法进行数值的推导然后与自己代码的遍历数值进行比较

public static int uniquePaths(int m, int n) { int[][] dp = new int[m][n]; //初始化 for (int i = 0; i < m; i++) { dp[i][0] = 1; } for (int i = 0; i < n; i++) { dp[0][i] = 1; } ​ for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = dp[i-1][j]+dp[i][j-1]; } } return dp[m-1][n-1]; }
class Solution: def uniquePaths(self, m: int, n: int) -> int: # 创建一个二维列表用于存储唯一路径数 dp = [[0] * n for _ in range(m)] # 设置第一行和第一列的基本情况 for i in range(m): dp[i][0] = 1 for j in range(n): dp[0][j] = 1 # 计算每个单元格的唯一路径数 for i in range(1, m): for j in range(1, n): dp[i][j] = dp[i - 1][j] + dp[i][j - 1] # 返回右下角单元格的唯一路径数 return dp[m - 1][n - 1]

总结

动态规划是一种非常实用的算法思想,会被用来解决很多的问题,可能平常做算法的时候已经用到了这种思想,但是并没有注意,虽然以上写了一些看似固定的算法模板,但是这种算法思想仍然需要熟练的情况才能够信手拈来,如果想深入学习可以看看贪心算法,贪心和动规有一定的相似性,但是贪心是完全没有固定公式的,需要具备全面的算法思想。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 15:48:01

文档检索软件self searcher绿色版下载

兼具本地文件名查找和文件内容查找&#xff0c;相当于everythinganytxt searcher: 通过百度网盘分享的文件&#xff1a;Self-Sea… 链接:https://pan.baidu.com/s/159OrBfTmGO5xO59Fia6Xlg?pwd6sx3 复制这段内容打开「百度网盘APP 即可获取」

作者头像 李华
网站建设 2026/7/14 15:48:00

JavaScript同时触发多个函数的5种高效方法

在JavaScript/HTML中通过onclick触发多个函数 在Web开发中&#xff0c;onclick事件常用于响应用户的点击操作。实际场景中可能需要同时触发多个函数&#xff0c;例如表单提交时验证数据、记录日志、发送请求等。以下是几种实现方式及代码示例。方法一&#xff1a;在HTML中直接调…

作者头像 李华
网站建设 2026/7/14 15:48:02

初识神经网络代码

神经网络项目一般分为以下3个模块&#xff0c;数据处理&#xff0c;模型搭建&#xff0c;参数设置数据处理部分class CovidDataset(Dataset):def __init__(self, file_path, mode):# 打开指定路径的文件&#xff0c;以只读模式读取with open(file_path, "r") as f:# …

作者头像 李华
网站建设 2026/7/14 15:48:15

算法设计与分析里面的渐进符号难以理解

算法设计中的渐进符号&#xff08;Asymptotic Notation&#xff09;之所以让人觉得抽象&#xff0c;是因为它跳出了具体代码的细节&#xff0c;转而去研究“当数据量变得无穷大时&#xff0c;算法耗时的增长趋势”。为了让你彻底理解这个概念&#xff0c;我们可以把它想象成一套…

作者头像 李华
网站建设 2026/7/14 15:48:17

毕业季论文救星:百考通AI如何帮你破解AIGC与重复率双重困局

深夜&#xff0c;知网查重报告上刺眼的红色标记和AIGC高疑似度警告&#xff0c;让无数本科生陷入焦虑。而今&#xff0c;一个专业工具的四大功能板块&#xff0c;正成为破解这一困局的系统性解决方案。 “改到凌晨三点&#xff0c;重复率还是下不去。” “AI帮我写的部分被标为…

作者头像 李华