我是靠谱客的博主 喜悦发夹,这篇文章主要介绍LeetCode 120. 三角形最小路径和120. 三角形最小路径和参考资料,现在分享给大家,希望可以做个参考。

120. 三角形最小路径和

题目描述

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

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

你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题吗?

解题思路

若定义 f(i, j) 为 (i, j) 点到底边的最小路径和,则易知递归求解式为:

f(i, j) = min(f(i + 1, j), f(i + 1, j + 1)) + triangle[i][j]

由此,我们将任一点到底边的最小路径和,转化成了与该点相邻两点到底边的最小路径和中的较小值,再加上该点本身的值。

思路一: 递归

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** * @param {number[][]} triangle * @return {number} */ var minimumTotal = function(triangle) { const dfs = function (i, j) { if (i == triangle.length) { return 0; } return Math.min(dfs(i + 1, j), dfs(i + 1, j + 1)) + triangle[i][j]; } return dfs(0, 0); };

暴力搜索会有大量的重复计算,导致 超出时间限制.

优化版本
利用二维数组进行记忆化

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** * @param {number[][]} triangle * @return {number} */ var minimumTotal = function(triangle) { let len = triangle.length, memo = Array.from(Array(len), () => Array(len)) const dfs = function (i, j) { if (i == len) { return 0; } if (memo[i][j] != null) { return memo[i][j]; } return memo[i][j] = Math.min(dfs(i + 1, j), dfs(i + 1, j + 1)) + triangle[i][j]; } return dfs(0, 0); };
  • 时间复杂度:O( n 2 n^2 n2) ,n 为三角形的行数。
  • 空间复杂度:O( n 2 n^2 n2) ;

思路二: 动态规划

定义二维 dp 数组,将解法一中「自顶向下的递归」改为「自底向上的递推」。

1. 状态定义:
dp[i][j] 表示从点 (i, j) 到底边的最小路径和。

2、状态转移:
dp[i][j] = min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j]

3. 初始状态
一开始都初始化为0

4. 返回值
返回 dp[0][0]

实现代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/** * @param {number[][]} triangle * @return {number} */ var minimumTotal = function(triangle) { let len = triangle.length, // dp[i][j] 表示从点 (i, j) 到底边的最小路径和 dp = Array.from(Array(len + 1), () => Array(len + 1).fill(0)); // 从三角形的最后一行开始递推 for (let i = len - 1; i >= 0; i--) { for (let j = 0; j <= i; j++) { dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j]; } } return dp[0][0]; };
  • 时间复杂度:O( n 2 n^2 n2) ,n 为三角形的行数。
  • 空间复杂度:O( n 2 n^2 n2) ;

空间复杂度优化
在实际递推中我们发现,计算 dp[i][j] 时,只用到了下一行的 dp[i + 1][j] 和 dp[i + 1][j + 1] , 因此 dp数组 定义成一维数组就行, 这样可以将将 O( n 2 n^2 n2) 的空间复杂度优化成 O(n)
优化后代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** * @param {number[][]} triangle * @return {number} */ var minimumTotal = function(triangle) { let len = triangle.length; if (len == 1) { return triangle[0][0] } let dp = Array(len + 1).fill(0); // 从三角形的最后一行开始递推 for (let i = len - 1; i >= 0; i--) { for (let j = 0; j <= i; j++) { dp[j] = Math.min(dp[j], dp[j + 1]) + triangle[i][j]; } } return dp[0]; };

参考资料

https://leetcode.cn/problems/triangle/solution/di-gui-ji-yi-hua-dp-bi-xu-miao-dong-by-sweetiee/

最后

以上就是喜悦发夹最近收集整理的关于LeetCode 120. 三角形最小路径和120. 三角形最小路径和参考资料的全部内容,更多相关LeetCode内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(98)

评论列表共有 0 条评论

立即
投稿
返回
顶部