概述
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]
由此,我们将任一点到底边的最小路径和,转化成了与该点相邻两点到底边的最小路径和中的较小值,再加上该点本身的值。
思路一: 递归
/**
* @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);
};
暴力搜索会有大量的重复计算,导致 超出时间限制
.
优化版本
利用二维数组进行记忆化
/**
* @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]
实现代码如下:
/**
* @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)
优化后代码如下:
/**
* @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 120. 三角形最小路径和120. 三角形最小路径和参考资料所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复