# [120. 三角形最小路径和](https://leetcode.cn/problems/triangle) [English Version](/solution/0100-0199/0120.Triangle/README_EN.md) ## 题目描述 <!-- 这里写题目描述 --> <p>给定一个三角形 <code>triangle</code> ,找出自顶向下的最小路径和。</p> <p>每一步只能移动到下一行中相邻的结点上。<strong>相邻的结点 </strong>在这里指的是 <strong>下标</strong> 与 <strong>上一层结点下标</strong> 相同或者等于 <strong>上一层结点下标 + 1</strong> 的两个结点。也就是说,如果正位于当前行的下标 <code>i</code> ,那么下一步可以移动到下一行的下标 <code>i</code> 或 <code>i + 1</code> 。</p> <p> </p> <p><strong>示例 1:</strong></p> <pre> <strong>输入:</strong>triangle = [[2],[3,4],[6,5,7],[4,1,8,3]] <strong>输出:</strong>11 <strong>解释:</strong>如下面简图所示: <strong>2</strong> <strong>3</strong> 4 6 <strong>5</strong> 7 4 <strong>1</strong> 8 3 自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。 </pre> <p><strong>示例 2:</strong></p> <pre> <strong>输入:</strong>triangle = [[-10]] <strong>输出:</strong>-10 </pre> <p> </p> <p><strong>提示:</strong></p> <ul> <li><code>1 <= triangle.length <= 200</code></li> <li><code>triangle[0].length == 1</code></li> <li><code>triangle[i].length == triangle[i - 1].length + 1</code></li> <li><code>-10<sup>4</sup> <= triangle[i][j] <= 10<sup>4</sup></code></li> </ul> <p> </p> <p><strong>进阶:</strong></p> <ul> <li>你可以只使用 <code>O(n)</code> 的额外空间(<code>n</code> 为三角形的总行数)来解决这个问题吗?</li> </ul> ## 解法 <!-- 这里可写通用的实现逻辑 --> 动态规划。自底向上。 <!-- tabs:start --> ### **Python3** <!-- 这里可写当前语言的特殊实现逻辑 --> ```python class Solution: def minimumTotal(self, triangle: List[List[int]]) -> int: n = len(triangle) dp = [[0] * (n + 1) for _ in range(n + 1)] for i in range(n - 1, -1, -1): for j in range(i + 1): dp[i][j] = min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j] return dp[0][0] ``` 空间优化: ```python class Solution: def minimumTotal(self, triangle: List[List[int]]) -> int: n = len(triangle) dp = [0] * (n + 1) for i in range(n - 1, -1, -1): for j in range(i + 1): dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j] return dp[0] ``` ### **Java** <!-- 这里可写当前语言的特殊实现逻辑 --> ```java 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]; } } ``` ### **C++** ```cpp class Solution { public: int minimumTotal(vector<vector<int>>& triangle) { int n = triangle.size(); vector<int> dp(n + 1); for (int i = n - 1; i >= 0; --i) for (int j = 0; j <= i; ++j) dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j]; return dp[0]; } }; ``` ### **Go** ```go func minimumTotal(triangle [][]int) int { n := len(triangle) dp := make([]int, n+1) for i := n - 1; i >= 0; i-- { for j := 0; j <= i; j++ { dp[j] = min(dp[j], dp[j+1]) + triangle[i][j] } } return dp[0] } func min(a, b int) int { if a < b { return a } return b } ``` ### **TypeScript** ```ts function minimumTotal(triangle: number[][]): number { const n = triangle.length; for (let i = n - 2; i >= 0; i--) { for (let j = 0; j < i + 1; j++) { triangle[i][j] += Math.min( triangle[i + 1][j], triangle[i + 1][j + 1], ); } } return triangle[0][0]; } ``` ### **Rust** ```rust impl Solution { pub fn minimum_total(mut triangle: Vec<Vec<i32>>) -> i32 { let n = triangle.len(); for i in (0..n - 1).rev() { for j in 0..i + 1 { triangle[i][j] += triangle[i + 1][j].min(triangle[i + 1][j + 1]); } } triangle[0][0] } } ``` ### **...** ``` ``` <!-- tabs:end -->