891 字
4 分钟
LeetCode刷题(三角形最小路径和、不同路径Ⅱ)

三角形最小路径和#

题目描述#

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

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

题解#

解法一:递归(超时27/46)

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        return  dfs(triangle, 0, 0);
    }

    private 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);
    }
}

解法二:在上述基础上添加记忆,避免重复计算

class Solution {
    Integer[][] memory;
    public int minimumTotal(List<List<Integer>> triangle) {
        memory = new Integer[triangle.size()][triangle.size()];
        return dfs(triangle, 0, 0);
    }

    public int dfs(List<List<Integer>> triangle, int i, int j) {
        if(triangle.size() == i) {
            return 0;
        }
        if(memory[i][j] != null) {
            return memory[i][j];
        }
        memory[i][j] = Math.min(dfs(triangle, i + 1, j), dfs(triangle, i + 1, j + 1)) + triangle.get(i).get(j);
        return memory[i][j];
    }
}

解法三:动态规划求解

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

空间优化:对于每一层的开头的元素其实没必要存储层数,只需要存储下一层的对应位置以及后续一个位置就可以规划出当前行的取值,而不影响之后的元素计算

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();
        int[] dp = new int[n + 1];
        for(int i = n - 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];
    }
}

不同路径Ⅱ#

题目描述#

给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角(即 grid[0][0])。机器人尝试移动到 右下角(即 grid[m - 1][n - 1])。机器人每次只能向下或者向右移动一步。

网格中的障碍物和空位置分别用 10 来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。

返回机器人能够到达右下角的不同路径数量。

示例 1:

465

输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右

示例 2:

466

输入:obstacleGrid = [[0,1],[0,0]]
输出:1

题解#

当遇到障碍的时候停止初始的横向纵向初始化,因为后面的都到达不了,之后如果当前的位置不是障碍物则用上左的结果相加赋值当前结果

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int row = obstacleGrid.length;
        int col = obstacleGrid[0].length;
        int[][] dp = new int[row][col];
        if(obstacleGrid[0][0] == 0) {
            dp[0][0] = 1;
        }
        int i = 1;
        while(i < row && obstacleGrid[i][0] != 1) {
            dp[i][0] = dp[i - 1][0]; 
            i++;
        }
        int j = 1;
        while(j < col && obstacleGrid[0][j] != 1) {
            dp[0][j] = dp[0][j - 1];
            j++;
        }
        for(i = 1; i < row; i++) {
            for(j = 1; j < col; j++) {
                if(obstacleGrid[i][j] != 1) {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[row - 1][col - 1];
    }
}
LeetCode刷题(三角形最小路径和、不同路径Ⅱ)
https://thrinisty.github.io/Blog/posts/leetcode刷题三角形最小路径和不同路径ⅱ/
作者
Thrinisty
发布于
2025-11-26
许可协议
CC BY-NC-SA 4.0