三角形最小路径和-java

本文介绍了如何使用递归和动态规划方法解决三角形中自顶向下最小路径和的问题,通过递归定义函数和动态规划数组dp计算路径和,避免了重复计算,提高了效率。
摘要由CSDN通过智能技术生成
  • 题目描述:

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

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

  •   

  • 解题思想:

    • 1.递归求解

      • 观察三角形的性质,可以发现从底部开始向上计算更为方便。因此,可以定义 f(i, j) 为从位置 (i, j) 到底部的最小路径和,其递归关系可以表示为:
        [ f(i, j) = \triangle[i][j] + \min(f(i + 1, j), f(i + 1, j + 1)) ]
        这里,triangle[i][j] 表示三角形中 (i, j) 处的值,而 f(i + 1, j) 和 f(i + 1, j + 1) 分别表示从下一行的相邻位置到底部的最小路径和。我们选择这两者中的较小值,加上当前位置的值,即可得到 f(i, j) 的值。

    • 2.动态规划求解

      • 根据上述递归关系,可以使用动态规划来求解问题。从三角形的底部开始向上逐行计算 f(i, j),直至顶部位置 (0, 0)。具体步骤如下:

        • 从三角形底部开始初始化 f(i, j),即最后一行的元素直接赋值为三角形对应位置的值。
        • 从倒数第二行开始,依次计算每个位置 (i, j) 的 f(i, j),根据递推关系求解:[ f(i, j) = \triangle[i][j] + \min(f(i + 1, j), f(i + 1, j + 1)) ]
        • 最终,f(0, 0) 就是从顶部到底部的最小路径和。

  • 法一: 递归

    • 1.定义递归函数
      • 首先,需要定义一个递归函数,该函数负责解决原始问题的子问题。递归函数的参数通常包括原始输入以及额外的参数用于标识当前处理的位置或状态。

    • 2.确定基本情况
      • 在递归函数中,需要确定基本情况,即递归的终止条件。这些基本情况通常对应于原始问题的最小规模情况,它们的解可以直接计算得到而不需要进一步的递归调用。

    • 3.递归调用
      • 在递归函数中,对于每个子问题,需要通过递归调用相同的函数来解决它。递归调用的参数通常是根据问题的分解而确定的,以便在下一步中处理不同的子问题。

    • 4.返回结果
      • 最后,递归函数需要返回原始问题的解。在递归过程中,每个递归调用都会返回其子问题的解,而在最终的递归调用中,会将所有子问题的解合并为原始问题的解,并返回给调用者。

    • 通过这些步骤,可以构建一个递归算法来解决各种类型的问题。然而,需要注意的是,递归算法可能会面临性能问题和重复计算等挑战,因此在实际应用中需要谨慎使用并考虑其他解决方案。

  • 代码实现(在力扣中, 会出现运行超时的情况, 建议使用动态规划解决)

    • class Solution {
          public int minimumTotal(List<List<Integer>> triangle){
              return dfs(triangle, 0, 0);
          }
      
          public int dfs(List<List<Integer>> triangle, int i, int j){
              if(i == triangle.size()) return 0;
      
              return Math.min(dfs(triangle, i + 1, j), dfs(triangle, i + 1, j + 1)) + triangle.get(i).get(j);
          }
      }

  • 法二: 动态规划

    • 1.首先,我们创建了一个长度为三角形行数加一的数组 dp,用来存储每一行的最小路径和。数组 dp 的索引 i 对应于三角形的第 i 行。

    • 2.然后,我们从三角形的倒数第二行开始向上遍历,对每一行中的每个元素进行处理。

    • 3.在每一行的处理中,我们使用一个内部循环来遍历该行的每个元素。对于当前处理的元素 triangle.get(i).get(j),我们通过比较其下方两个相邻元素的 dp 值,选择较小的那个,并加上当前元素的值。这样就得到了当前位置的最小路径和,并将其存储在 dp[j] 中。

    • 4.在处理完所有行后,dp[0] 中存储的就是整个三角形的最小路径和,因为它是位于三角形顶部的元素,经过了所有行的比较和累加。

    • 5.最后,我们将 dp[0] 返回作为最终结果。

    • 这段代码的时间复杂度为 O(n`2),其中 n 是三角形的行数。因为我们只使用了一个长度为 n + 1 的数组 dp 来存储中间结果,所以空间复杂度为 O(n)。

  • 以下是代码实现:

    • class Solution {
          public int minimumTotal(List<List<Integer>> triangle){
              int[] dp = new int[triangle.size() + 1];
      
              for(int i = triangle.size() - 1; i >= 0; i--){
                  for(int j = 0; j <= i; j++)
                      dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j);
              }
              return dp[0];
          }
      }

        

  •                             以上是本篇文章的全部内容, 感谢观看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值