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

Leetcode 剑指 Offer II 100.三角形最小路径和

题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定一个三角形 triangle ,找出自顶向下的最小路径和。

每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。

示例 1:

  • 输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
  • 输出:11
  • 解释:如下面简图所示:
   23 46 5 7
4 1 8 3

自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

示例 2:

  • 输入:triangle = [[-10]]
  • 输出:-10

提示:

  • 1 <= triangle.length <= 200
  • triangle[0].length == 1
  • triangle[i].length == triangle[i - 1].length + 1
  • -10^4 <= triangle[i][j] <= 10^4

进阶:

  • 你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题吗?

题目思考

  1. 如何优化算法复杂度?

解决方案

  • 分析题目, 每一步只能移动到下一行中相邻的结点上, 我们可以利用这一点, 根据上一行下标 i 的最小路径和来更新当前行下标 i 和 i+1 的最小路径和
  • 显然这就是动态规划的思路:
    • dp[r][i] 代表第 r 行第 i 个下标的最小路径和
    • 初始化 dp[0][0] = triangle[0][0], 其他值全是 inf, 表示开始时只有起点的路径和确定
    • 然后进行状态转移, 对于第 r 行的第 i 个下标: dp[r][i] = triangle[r][i]+min(dp[r-1][i-1],dp[r][i] (如果 r 或 i 为 0, 则相应的 r-1 或 c-1 的 dp 值就是 inf, 表示不能从该方向转移而来)
    • 这样最后一行的最小 dp 值就代表整个三角形的最小路径和
  • 这里可以额外进行一些优化, 将二维 dp 数组优化成一维, 这样就可以满足题目的进阶要求
  • 具体做法就是只存储前一行和当前行的 dp 值, 记为 pdp 和 dp, 由于最后一行元素数目为 n, 所以整体空间复杂度就是 O(n)
  • 然后在计算第 r 行的 dp 值时, 遍历 pdp, 根据 pdp[i] 的值, 更新 dp[i]dp[i+1]
  • 计算完毕后, 再将 dp 赋值给 pdp, 用于下一行的计算
  • 下面的代码有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(N^2): 需要两重循环求 DP 值
  • 空间复杂度 O(N): 最多使用长度为 N 的 dp 数组
代码
class Solution:def minimumTotal(self, triangle: List[List[int]]) -> int:### 动态规划+滚动数组n = len(triangle)# pdp存储上一行的最小路径, 初始化为第0行pdp = triangle[0]for r in range(1, n):# 初始化当前行的最小路径为+infdp = [float("inf")] * len(triangle[r])for i in range(len(pdp)):# 状态转移, 上一行的下标i可以移动到i或者i+1, 更新当前行对应下标的最小路径和dp[i] = min(dp[i], triangle[r][i] + pdp[i])dp[i + 1] = min(dp[i + 1], triangle[r][i + 1] + pdp[i])pdp = dp# 最终结果就是最后一行的最小路径和return min(pdp)

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我


http://www.mrgr.cn/news/63889.html

相关文章:

  • 用Pyhon写一款简单的益智类小游戏——2048
  • 全新大模型框架Haystack,搭建RAG pipeline
  • 论文概览 |《Journal of Transport Geography》2024.10 Vol.120
  • 【Linux】用户权限管理:创建受限用户并配置特定目录访问权限
  • 如何解决docker镜像下载失败问题
  • float(‘inf‘)中inf是什么意思
  • OR63 删除公共字符
  • 【JAVA 笔记】10 ch07_oop_fundamentals 面向对象编程(基础部分)
  • Linux网络配置与管理:掌握访问与管理的关键技能
  • C++ | Leetcode C++题解之第526题优美的排列
  • 闪存学习_1:Flash-Aware Computing from Jihong Kim
  • nodejs入门教程1:nodejs简介
  • 聊一聊Elasticsearch的索引的分片分配机制
  • 更懂你的AI助手来了
  • C#/.NET/.NET Core技术前沿周刊 | 第 11 期(2024年10.21-10.31)
  • 线性数据结构之队列
  • 字符串函数
  • 数据采集-Kepware 安装证书异常处理
  • 【特征值处理】
  • 树莓派基本设置--8.播放音频和视频
  • 探索Python新境界:Buzhug库的神秘面纱
  • 使用Jupyter Notebook进行数据科学项目
  • centos7 keepalived 安装一共有几种方式?
  • 2021-10-22 51蛋骗鸡按键控制上电LED和电机正反转
  • Android中的跨进程通信方案总结一-AIDL的使用
  • fastboot相关的命令大全