力扣第120题-三角形最小路径和

554 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

前言

力扣第120题 三角形最小路径和 如下所示:

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

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

示例 1:

输入: triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
输出: 11
解释: 如下面简图所示:
   2
  3 4
 6 5 7
4 1 8 3
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

示例 2:

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

一、思路

这一题我看到的第一想法就是使用 递归 来实现的。递归大致的思路是:从上刀下,依次选择所有的节点。只有选择到最后一层的节点时,取最小的路径和。

递归代码实现如下图所示:

image.png

但是非常可惜的是,使用递归会导致超时。

image.png

于是不得以换一个解法,于是就尝试了使用 动态规划 来解决这一题。

动态规划

我们假设 dp[i][j] 为从顶点到 第 i 行第 j 列 最小的路径和。

  1. 边界情况

对于第一列来说,只能竖直向下才能达到。故 dp[i][0] += dp[i-1][0] + triangle.get(i).get(0)

  1. 状态转移方程

dp[i][j] 的值与什么有关系呢?

有如下两种情况:

  • j > i-1 时,dp[i][j] = triangle.get(i).get(j) + dp[i-1][j-1]。即到达下一行的最后一个元素是,只能选择上一行的最后一个元素
  • 其他情况:dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + arr[i][j],(i > 0, j > 0

最后我们取 dp 最后一行最小值,结果就是到达最后一层最小的路径和

二、实现

实现代码

实现代码与思路中完全保持一致

    public int minimumTotal(List<List<Integer>> triangle) {
        int ret = Integer.MAX_VALUE;
        int m = triangle.size(), n = triangle.get(triangle.size()-1).size();
        int[][] dp = new int[m][n];
        // 初始化第一列
        dp[0][0] = triangle.get(0).get(0);
        for (int i=1; i<n; i++){
            dp[i][0] += dp[i-1][0] + triangle.get(i).get(0);
        }
        for (int i=1; i<m; i++){
            for (int j=1; j<=i; j++){
                if (j > i-1){
                    dp[i][j] = triangle.get(i).get(j) + dp[i-1][j-1];
                } else {
                    dp[i][j] = triangle.get(i).get(j) + Math.min(dp[i-1][j], dp[i-1][j-1]);
                }
            }
        }
        // 取最后一行的最小值
        for(int i=0; i<n; i++){
            ret = Math.min(ret, dp[m-1][i]);
        }
        return ret;
    }

测试代码

    public static void main(String[] args) {
        List<List<Integer>> list = new ArrayList<>(){
            {
                add(Arrays.asList(2));
                add(Arrays.asList(3,4));
                add(Arrays.asList(6,5,7));
                add(Arrays.asList(4,1,8,3));
            }
        };
        List<List<Integer>> list1 = new ArrayList<>(){
            {
                add(Arrays.asList(-1));
                add(Arrays.asList(-2,-3));
            }
        };
        int ret = new Number120().minimumTotal(list);
        System.out.println(ret);
    }

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~