algorighm/top-interview-leetcode150/dynamic-planning/120三角形最小路径和.js
2025-06-26 23:36:36 +08:00

75 lines
2.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @param {number[][]} triangle
* @return {number}
*/
const minimumTotal = function (triangle) {
};
/*
思路:
这是一个典型的「从上到下」的动态规划问题,三角形的每个位置只能由上一层的相邻两个位置转移而来。
定义状态:
- dp[i][j] 表示从顶点走到位置 (i, j) 的最小路径和
状态转移方程:
- 左边界dp[i][0] = dp[i-1][0] + triangle[i][0]
- 中间dp[i][j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j]
- 右边界dp[i][i] = dp[i-1][i-1] + triangle[i][i]
初始化:
- dp[0][0] = triangle[0][0]
返回值:
- 最后一层中的最小值,即 Math.min(...dp[n - 1])
*/
function f1(triangle) {
const n = triangle.length;
const dp = Array.from({ length: n }, (_, i) => Array(i + 1).fill(0));
dp[0][0] = triangle[0][0];
for (let i = 1; i < n; i++) {
const len = triangle[i].length;
// 左边界,只能从上一行第一个元素来
dp[i][0] = dp[i - 1][0] + triangle[i][0];
// 中间部分,来自上一行的[j - 1] 和 [j]
for (let j = 1; j < len - 1; j++) {
dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j];
}
// 右边界,只能从上一行最后一个元素来
dp[i][len - 1] = dp[i - 1][len - 2] + triangle[i][len - 1];
}
return Math.min(...dp[n - 1]);
}
/*
不重复计算len - 1
*/
function f2(triangle) {
const n = triangle.length;
const dp = Array.from({ length: n }, (_, i) => Array(i + 1).fill(0));
dp[0][0] = triangle[0][0];
for (let i = 1; i < n; i++) {
const len = triangle[i].length;
const last = len - 1;
// 左边界,只能从上一行第一个元素来
dp[i][0] = dp[i - 1][0] + triangle[i][0];
// 中间部分,来自上一行的[j - 1] 和 [j]
for (let j = 1; j < last; j++) {
dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j];
}
// 右边界,只能从上一行最后一个元素来
dp[i][last] = dp[i - 1][last - 1] + triangle[i][last];
}
return Math.min(...dp[n - 1]);
}