当前位置: 首页 > news >正文

【LeetCode 热题 100】64. 最小路径和——(解法二)递推

Problem: 64. 最小路径和

文章目录

  • 整体思路
  • 完整代码
  • # 时空复杂度
    • 时间复杂度:O(m * n)
    • 空间复杂度:O(m * n)

整体思路

这段代码同样旨在解决 “最小路径和” 问题,但它采用的是一种 自底向上(Bottom-Up)的动态规划 方法,也称为 迭代法制表法 (Tabulation)。这种方法通过构建一个DP表(dp 二维数组),从起点开始,逐步计算出到达每个格子的最小路径和,最终得到终点的答案。

该实现通过巧妙地增加DP数组的维度并设置哨兵值,将边界条件的处理融入到统一的状态转移方程中,使得代码结构清晰。

  1. 状态定义与索引映射

    • 算法定义了一个二维DP数组 dp,大小为 (m+1) x (n+1)
    • dp[i][j] 的含义是:从起点 grid[0][0] 到达网格中的点 grid[i-1][j-1] 的最小路径和
    • 这是一个索引偏移的技巧。dp 数组的索引 (i, j) 对应了 m x n 网格中的索引 (i-1, j-1)
  2. 基础情况与边界处理 (Base Cases & Boundary Handling)

    • 设置“墙壁”:代码首先将 dp 数组的第0行和第0列(除了 dp[0][0]dp[1][0] 等)填充为 Integer.MAX_VALUE。这相当于在网格的上方和左方建立了一堵无限高的“墙”,确保路径只能从有效的格子内部过来,而不会从“网格外部”以一个较小的值(比如0)进入计算,从而干扰 Math.min 的结果。
    • 设置起点if (i == 0 && j == 0) 这个条件在循环内部处理了起点。dp[1][1] 被设置为 grid[0][0] 的值。这是整个DP计算的起点。
  3. 状态转移 (State Transition)

    • 算法使用两层嵌套循环来填充DP表。循环变量 ij 对应的是 m x n 网格的索引。
    • 在循环的每一步,计算 dp[i+1][j+1] 的值。
    • 状态转移方程是 dp[i + 1][j + 1] = Math.min(dp[i][j + 1], dp[i + 1][j]) + grid[i][j]
    • 我们来解析这个方程:
      • 要到达 grid[i][j](对应 dp[i+1][j+1]),只能从其上方的 grid[i-1][j](对应 dp[i][j+1])或左方的 grid[i][j-1](对应 dp[i+1][j])过来。
      • 因此,到达 grid[i][j] 的最小路径和,等于 grid[i][j] 的值加上“到达上方格子的最小路径和”与“到达左方格子的最小路径和”中的较小者。
      • 由于我们在第0行和第0列设置了极大值,当 i=0 时,dp[i][j+1] (即dp[0][j+1]) 是极大值,Math.min 会自动选择 dp[i+1][j],正确地处理了第一行的情况。对第一列同理。
  4. 返回结果

    • 当所有循环结束后,dp 数组已经完全填充。我们需要的最终答案,即到达终点 grid[m-1][n-1] 的最小路径和,就存储在 dp[m][n] 中。

完整代码

import java.util.Arrays;class Solution {/*** 计算从 m x n 网格左上角到右下角的最小路径和。* @param grid 包含非负整数的二维网格* @return 最小路径和*/public int minPathSum(int[][] grid) {int m = grid.length;int n = grid[0].length;// dp[i][j]: 表示从起点到网格 (i-1, j-1) 的最小路径和。// 使用 m+1, n+1 的大小是为了用第0行和第0列作为边界“墙”。int[][] dp = new int[m + 1][n + 1];// 初始化边界:将第0行设为极大值,作为上方的“墙”。Arrays.fill(dp[0], Integer.MAX_VALUE);// 遍历原始网格的行for (int i = 0; i < m; i++) {// 初始化边界:将每行的第0列设为极大值,作为左方的“墙”。dp[i + 1][0] = Integer.MAX_VALUE;// 遍历原始网格的列for (int j = 0; j < n; j++) {// 处理起点 (0,0) 的特殊情况if (i == 0 && j == 0) {// dp[1][1] 对应网格 (0,0),其最小路径和就是它自身的值。dp[1][1] = grid[i][j];} else {// 状态转移方程:// 到达网格 (i,j) 的最小路径和,等于// min(到达上方格子的最小和, 到达左方格子的最小和) + 当前格子的值。// dp[i][j+1] -> 上方格子// dp[i+1][j] -> 左方格子dp[i + 1][j + 1] = Math.min(dp[i][j + 1], dp[i + 1][j]) + grid[i][j];}}}// 最终答案是到达网格 (m-1, n-1) 的路径数,对应 dp[m][n]。return dp[m][n];}
}

# 时空复杂度

时间复杂度:O(m * n)

  1. 循环结构:算法使用了两层嵌套的 for 循环。
    • 外层循环从 i = 0 运行到 m-1,执行 m 次。
    • 内层循环从 j = 0 运行到 n-1,执行 n 次。
  2. 计算依据
    • 总的操作次数是内外层循环次数的乘积,即 m * n。初始化边界的操作复杂度是 O(m+n),被 m*n 主导。

综合分析
算法的时间复杂度为 O(m * n)

空间复杂度:O(m * n)

  1. 主要存储开销:算法创建了一个名为 dp 的二维整型数组来存储动态规划的所有中间状态。
  2. 空间大小:该数组的大小是 (m + 1) * (n + 1)

综合分析
算法所需的额外空间主要由 dp 数组决定,其空间复杂度为 O(m * n)

http://www.dtcms.com/a/359514.html

相关文章:

  • 需要固定一个指针,再遍历另一个指针的都可以用双指针方法
  • 分布式锁和分布式事务
  • 刷算法题-数组-02
  • Wend看源码-marker(RAG工程-PDF文件解析)
  • isp图像处理--bayer Binning
  • UVM APB 验证 VIP Agent 逻辑架构与数据流图
  • 大话 IOT 技术(1) -- 架构篇
  • Week 14: 深度学习补遗:迁移学习
  • 设计模式在Java中的应用:从单例模式到工厂模式的全面解析!
  • C++11——万能模板及完美转发
  • redis详解 (最开始写博客是写redis 纪念日在写一篇redis)
  • 雪花算法实现分布式环境下的高效动态ID生成
  • 扩展:如何设计与实现一个微服务架构下的跨服务异常处理适配器?
  • redis----zset详解
  • 数值分析——非线性方程与方程组的数值解法之二分法
  • 创意无界:云渲染如何让视觉创作触手可及
  • 责任链模式实践-开放银行数据保护及合规
  • 模型系列(篇三)-Llama
  • 分布式事务相关
  • 【MYSQL】从混乱到清晰:联合查询帮你打通数据孤岛
  • Python 实战:内网渗透中的信息收集自动化脚本(6)
  • React前端开发_Day11
  • Pytest+Selenium4 Web自动化测试框架(三日速通)
  • 数据中心网络实现梳理
  • 变频器实习总结14 电子元件中的内部参考电压 Type-c口对于BMS开发的优点
  • Caffeine TimerWheel时间轮 深度解析:O(1)复杂度增删和触发时间事件
  • 2025.8.31基于UDP的网络聊天室项目
  • 数值分析——非线性方程与方程组的数值解法之迭代法
  • Nginx虚拟主机配置
  • 从RNN到BERT