力扣 LCR 099. 最小路径和 —— 动态规划入门详解
引言动态规划的核心在于将复杂问题分解为重叠子问题而「最小路径和」正是理解这一思想的经典范例。给定一个带权网格每次只能向下或向右移动求从左上到右下的最小路径和。这道题相比「粉刷房子」多了一个二维空间维度但状态转移更加直观——每个格子的值只依赖于其上方和左方的格子。本文将带你从 DP 表格构造到代码实现一步步掌握这道必刷题摘要本文详细解析力扣 LCR 099. 最小路径和的动态规划解法。给定m×n非负网格每次只能向下或向右走求左上到右下的最小路径和。定义dp[i][j]为到达(i,j)的最小路径和转移方程dp[i][j] grid[i][j] min(dp[i-1][j], dp[i][j-1])上格子/左格子二者取较小值。重点讲解初始化边界第一行只能从左边来第一列只能从上边来需先填好第一行、第一列这种边界值然后再开始动态规划。提供二维数组和 O(n) 空间优化两种代码时间复杂度 O(m×n)目录一、题目描述二、动态规划思路1. 为什么用 DP2. DP 数组的定义3. DP 数组的构造以示例 1 为例第一步初始化 dp 数组第二步从 (1,1) 开始递推双层循环4. 状态转移方程三、Java 代码实现四、代码优化空间压缩五、易错点总结特别重要⚠️ 注意点 1初始化边界不能忘⚠️ 注意点 2理清上一步来自哪里⚠️ 注意点 3空间优化时一维数组的含义六、复杂度分析总结一、题目描述给定一个包含非负整数的m x n网格grid请找出一条从左上角到右下角的路径使得路径上的数字总和为最小。说明每次只能向下或者向右移动一步。示例 1输入grid [[1,3,1],[1,5,1],[4,2,1]] 输出7 解释路径 1→3→1→1→1 的总和最小。示例 2输入grid [[1,2,3],[4,5,6]] 输出12提示m grid.lengthn grid[i].length1 m, n 2000 grid[i][j] 200二、动态规划思路1. 为什么用 DP到达(i,j)的最小路径和只依赖于到达上方(i-1,j)和左方(i,j-1)的最小路径和。因为每次只能向下或向右所以(i,j)的上一步只能是上面或左面——这就是最优子结构适合用 DP 自顶向下推导。2. DP 数组的定义dp[i][j]从左上角 (0,0) 走到 (i,j) 的最小路径和。3. DP 数组的构造以示例 1 为例输入grid [[1,3,1], [1,5,1], [4,2,1]]第一步初始化 dp 数组① 起点dp[0][0] grid[0][0] 1② 初始化第一行只能从左边来dp[0][j] dp[0][j-1] grid[0][j]即dp[0][1] dp[0][0] grid[0][1] 1 3 4dp[0][2] dp[0][1] grid[0][2] 4 1 5③ 初始化第一列只能从上边来dp[i][0] dp[i-1][0] grid[i][0]即dp[1][0] dp[0][0] grid[1][0] 1 1 2dp[2][0] dp[1][0] grid[2][0] 2 4 6初始化完成后dp 数组为下标\下标012014512待双层循环推导待双层循环推导26待双层循环推导待双层循环推导第二步从 (1,1) 开始递推双层循环对于非边界格子(i,j)其值 grid[i][j] min(dp[i-1][j], dp[i][j-1])dp[1][1] 5 min(dp[0][1]4, dp[1][0]2) 5 2 7dp[1][2] 1 min(dp[0][2]5, dp[1][1]7) 1 5 6dp[2][1] 2 min(dp[1][1]7, dp[2][0]6) 2 6 8dp[2][2] 1 min(dp[1][2]6, dp[2][1]8) 1 6 7完整 dp 数组下标\下标012014512762687最终答案dp[2][2] 74. 状态转移方程边界情况dp[0][0] grid[0][0]第一行dp[0][j] dp[0][j-1] grid[0][j]只能从左边来第一列dp[i][0] dp[i-1][0] grid[i][0]只能从上边来通用情况dp[i][j] grid[i][j] min(dp[i-1][j], dp[i][j-1])三、Java 代码实现class Solution { public int minPathSum(int[][] grid) { //1.获取矩阵的行数和列数 int row grid.length; int col grid[0].length; //2.创建dp数组 int[][] dp new int[row][col]; //3.初始化dp数组初始化边界值第一行、第一列 //初始化左上角元素 dp[0][0] grid[0][0]; //初始化第一列 for (int i 1; i row; i) { dp[i][0] dp[i - 1][0] grid[i][0]; } //初始化第一行 for (int j 1; j col; j) { dp[0][j] dp[0][j - 1] grid[0][j]; } //4.开始动态规划的核心代码填充dp数组 for(int i1;irow;i){ for(int j1;jcol;j){ //到达当前节点的最小路径 当前格子的耗费路径 min(到达左面相邻格子的最小路径 到达上面相邻格子的最小路径) dp[i][j] grid[i][j] Math.min(dp[i][j-1], dp[i-1][j]); } } //返回结果 return dp[row-1][col-1]; } }运行结果四、代码优化空间压缩因为dp[i][j]只依赖于当前行的左方和上一行的同列所以可以用一维数组滚动更新空间复杂度降至O(n)public static int minPathSum(int[][] grid) { int m grid.length; int n grid[0].length; int[] dp new int[n]; // 初始化第一行 dp[0] grid[0][0]; for (int j 1; j n; j) { dp[j] dp[j-1] grid[0][j]; } // 从第二行开始 for (int i 1; i m; i) { dp[0] grid[i][0]; // 第一列只能从上边来 for (int j 1; j n; j) { dp[j] grid[i][j] Math.min(dp[j], dp[j-1]); // dp[j]旧值代表上方dp[j-1]新值代表左方 } } return dp[n-1]; }五、易错点总结特别重要⚠️ 注意点 1初始化边界不能忘很多同学直接写双层循环导致i0或j0时dp[i-1][j]或dp[i][j-1]越界。正确做法先单独初始化第一行和第一列再从(1,1)开始循环。⚠️ 注意点 2理清上一步来自哪里因为只能向下或向右走所以到达(i,j)的上一步只能是上方(i-1,j)或左方(i,j-1)不是四个方向也不是斜对角。⚠️ 注意点 3空间优化时一维数组的含义滚动数组版本中dp[j]在更新前代表上一行(i-1,j)的值dp[j-1]已经更新为当前行(i,j-1)的值所以Math.min(dp[j], dp[j-1])正好对应min(dp[i-1][j], dp[i][j-1])不要搞反顺序。六、复杂度分析版本时间复杂度空间复杂度二维数组O(m × n)O(m × n)一维滚动数组O(m × n)O(n)总结这道题是动态规划中路径类问题的入门经典核心思想是定义dp[i][j]为到达(i,j)的最小路径和先初始化边界由于第一行的每个格子只可能从左方格子而来第一列的每个格子只可能从上方的格子而来。所以此时初始化边界就是先初始化第一行、第一列的每个格子的值。通用转移dp[i][j] grid[i][j] min(dp[i-1][j], dp[i][j-1])最终答案在dp[m-1][n-1]相比「粉刷房子」本题的 DP 表格多了一个空间维度但转移关系更加直观——上一步来自哪里一目了然。掌握这道题后可以继续挑战「不同路径」「三角形最小路径和」等同类问题。希望这篇文章能帮助你更好地理解动态规划如果有问题欢迎留言讨论

相关新闻

终极指南:如何在Windows任务栏实现桌面监控和性能优化

终极指南:如何在Windows任务栏实现桌面监控和性能优化

终极指南:如何在Windows任务栏实现桌面监控和性能优化 【免费下载链接】TrafficMonitorPlugins 用于TrafficMonitor的插件 项目地址: https://gitcode.com/gh_mirrors/tr/TrafficMonitorPlugins 还在为复杂的系统监控工具烦恼吗?每次想查看CPU温度…

2026/10/15 9:50:35 阅读更多 →
Stable-Baselines3 最佳实践:避免常见陷阱的 7 个实用技巧

Stable-Baselines3 最佳实践:避免常见陷阱的 7 个实用技巧

Stable-Baselines3 最佳实践:避免常见陷阱的 7 个实用技巧 【免费下载链接】rl-tutorial-jnrr19 Stable-Baselines tutorial for Journes Nationales de la Recherche en Robotique 2019 项目地址: https://gitcode.com/gh_mirrors/rl/rl-tutorial-jnrr19 S…

2026/10/13 15:40:42 阅读更多 →
OAuth-Plugin生成器详解:快速创建OAuth提供者和消费者

OAuth-Plugin生成器详解:快速创建OAuth提供者和消费者

OAuth-Plugin生成器详解:快速创建OAuth提供者和消费者 【免费下载链接】oauth-plugin Rails plugin for OAuth 项目地址: https://gitcode.com/gh_mirrors/oa/oauth-plugin OAuth-Plugin是一款专为Rails应用设计的插件,提供了强大的生成器功能&am…

2026/10/10 17:10:23 阅读更多 →

最新新闻

ASP.NET Core Cookie身份验证实现与安全配置指南

ASP.NET Core Cookie身份验证实现与安全配置指南

1. 身份验证基础与Cookie机制解析现代Web应用的身份验证主要有三种主流方式:Cookie认证、JWT令牌和OAuth协议。其中Cookie认证因其简单易用、浏览器原生支持的特性,成为ASP.NET Core中最常用的身份验证方案之一。Cookie本质上是一小段存储在客户端的文本…

2026/10/15 9:50:47 阅读更多 →
OpenClaw入门教程:从安装到上手的完整指南(TaoToken 统一 Key 接入版)

OpenClaw入门教程:从安装到上手的完整指南(TaoToken 统一 Key 接入版)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:50:47 阅读更多 →
LiteFlow-03:拥抱 Spring 生态 —— 自动化装配与独占高阶特性

LiteFlow-03:拥抱 Spring 生态 —— 自动化装配与独占高阶特性

LiteFlow-03:拥抱 Spring 生态 —— 自动化装配与独占高阶特性 在前面几章中,我们脱离了所有框架,在纯粹的 Non-Spring(原生 Java/Kotlin)环境下拆解了 LiteFlow 的底层内核。我们看到,原生模式虽然轻量&am…

2026/10/15 9:50:47 阅读更多 →
Positron Supervisor 的 Kallichore WebSocket 消息协议:SocketMessage 类型体系与消息消费链路

Positron Supervisor 的 Kallichore WebSocket 消息协议:SocketMessage 类型体系与消息消费链路

开发工具代码编辑器数据科学 【免费下载链接】positron Positron, a next-generation data science IDE 项目地址: https://gitcode.com/gh_mirrors/po/positron 点击查看 免费下载 导读 Kallichore(kcserver)是 Positron Supervisor 背后的…

2026/10/15 9:50:47 阅读更多 →
SpringBoot+Vue校园兼职系统开发实践

SpringBoot+Vue校园兼职系统开发实践

1. 项目概述这个基于SpringBoot的大学生兼职管理系统是一个面向高校学生群体的实用型Web应用。我在开发过程中发现,校园兼职市场存在信息不对称、管理混乱等问题,而传统的人工登记方式效率低下且容易出错。这套系统正是为了解决这些痛点而设计的。系统采…

2026/10/15 9:50:47 阅读更多 →
HyperFrames实战:用多帧堆叠提升夜景信噪比与动态范围

HyperFrames实战:用多帧堆叠提升夜景信噪比与动态范围

作为一个常年拍夜景、又不愿意每次都扛三脚架出门的人,我有一段时间被“高ISO噪点”和“单帧动态范围不够”这两件事反复折磨。后来干脆花几个周末写了一个命令行小工具,名字就叫 HyperFrames。它的思路特别朴素:既然单帧照片在短时间内只有那…

2026/10/15 9:49:45 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →