力扣LeetCode: 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

解法:动态规划

问题分析:

  • 我们需要从三角形的顶部到底部找到一条路径,使得路径上的数字之和最小。

  • 每一步只能移动到下一行相邻的节点(即当前行的下标 i 可以移动到下一行的下标 i 或 i + 1)。

动态规划思路:

  1. 状态定义

    • 设 dp[i][j] 表示从三角形顶部到第 i 行第 j 列的最小路径和。

  2. 状态转移方程

    • 对于第 i 行的第 j 列,可以从第 i-1 行的第 j-1 列或第 j 列移动而来。

    • 因此,状态转移方程为:

      dp[i][j]=triangle[i][j]+min⁡(dp[i−1][j−1],dp[i−1][j])dp[i][j]=triangle[i][j]+min(dp[i−1][j−1],dp[i−1][j])
    • 注意边界条件:

      • 如果 j == 0,只能从 dp[i-1][j] 移动而来。

      • 如果 j == i,只能从 dp[i-1][j-1] 移动而来。

  3. 初始条件

    • dp[0][0] = triangle[0][0],即三角形的顶部。

  4. 最终结果

    • 最终的最小路径和是 dp 数组最后一行的最小值。

优化空间复杂度:

  • 由于 dp[i][j] 只依赖于 dp[i-1][j-1] 和 dp[i-1][j],我们可以使用一维数组来优化空间复杂度。

  • 从下往上计算,可以避免覆盖问题。

代码实现:

class Solution {
public:
    int minimumTotal(vector>& triangle) {
        int n = triangle.size();
        // 从倒数第二行开始,向上计算
        for (int i = n - 2; i >= 0; --i) {
            for (int j = 0; j <= i; ++j) {
                // 更新当前行的最小路径和
                triangle[i][j] += min(triangle[i + 1][j], triangle[i + 1][j + 1]);
            }
        }
        // 返回顶部的值
        return triangle[0][0];
    }
};

代码解释:

  1. 从倒数第二行开始,逐行向上计算。

  2. 对于每一行的每个元素,更新其值为当前值加上下一行相邻两个元素的最小值。

  3. 最终,triangle[0][0] 就是自顶向下的最小路径和。

复杂度分析:

  • 时间复杂度:O(n2)O(n2),其中 nn 是三角形的行数。我们需要遍历每个元素。

  • 空间复杂度:O(1)O(1),直接在原数组上进行修改,没有使用额外空间。

你可能感兴趣的:(LeetCode,leetcode,算法,c++,动态规划)