登录
转载

leetcode- 三角形最小路径和

发布于 2025-01-10 阅读 58
  • GitHub
  • LeetCode
转载

三角形最小路径和

二 题目

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

每一步只能移动到下一行中相邻的结点上。

相邻的结点 在这里指的是 下标 与 上一层结点下标 相同

或者等于 上一层结点下标 + 1 的两个结点。

例如,给定三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

说明:

如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/triangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
 * @param {number[][]} triangle
 * @return {number}
 */
var minimumTotal = function(triangle) {

};

根据上面的已知函数,小伙伴们可以先尝试破解本题,确定了自己的答案后再看下面代码。

三 解题思路

首先,我们抛弃动态规划等优秀解答,写一个简单满足面试官要求的题解。

我们的思路很清晰:

拿其中一个例子说明,它的数据 routeList 的走向将如下:

[
     [-1],
    [3,2],
  [-3,1,-1],
]
------
[ -1 ]      
------      
[ 2, 1 ]    
------      
[ -1, 2, 0 ]
  1. 由顶往下靠,将每一步的最优解给提取出来
  2. 第一步的时候,组合 [-1], [],得到 [routeList, minSum][[-1], -1]
  3. 第二步的时候,组合 [3, 2], [-1],得到 [routeList, minSum][[2, 1], 1]
  4. 第三步的时候,组合 [-3, 1, -1], [2, 1],得到 [routeList, minSum][[-1, 2, 0], -1]
/**
* @name combine
* @description 简单版本 两两组合
* @param {any} arr1 数组 1
* @param {any} arr2 数组 2
*/
const combine = (arr1, arr2) => {
  const combineList = []; // 组合后的结果集
  let minSum = Number.MAX_SAFE_INTEGER; // 最小值

  // 如果是第一次传递
  if (!arr1.length) {
    minSum = arr2[0];
    return [arr2, minSum];
  }
  // 如果两个数组不为空
  for (let i = 0; i < arr2.length; i++) {
    let tempSum = Number.MAX_SAFE_INTEGER;
    for (let j = 0; j < arr1.length; j++) {
      // 很奇怪的是,题目标明了:
      // 每一步只能移动到下一行中相邻的结点上。
      // 相邻的结点 在这里指的是 下标 与 上一层结点下标 相同
      // 或者等于 上一层结点下标 + 1 的两个结点。
      // 然后我写了个 Math.abs(i - j) < 2,差点想得脑袋裂开
      if (i - j === 1 || i - j === 0) {
        tempSum = Math.min(arr2[i] + arr1[j], tempSum);
      }
    }
    minSum = Math.min(tempSum, minSum);
    combineList.push(tempSum);
  }
  return [combineList, minSum];
};

/**
 * @param {number[][]} triangle
 * @return {number}
 */
const minimumTotal = (triangle) => {
  // 思路:将所有路径找出来
  // 然后比较所有路径的总和,取最小的一个
  let routeList = [];
  let minSum = 0;
  for (let i = 0; i < triangle.length; i++) {
    [routeList, minSum] = combine(routeList, triangle[i]);
  }
  return minSum;
};

// 正常内容示例
console.log(minimumTotal(
  [
      [2],
     [3,4],
    [6,5,7],
   [4,1,8,3]
  ]
)); // 11

// 只有一个示例
console.log(minimumTotal(
  [
    [-10],
  ]
)); // -10

// Math.abs(i - j) < 2 错误示例
console.log(minimumTotal(
  [
       [-1],
      [3,2],
    [-3,1,-1],
  ]
)); // -1

满足基本需求,搞定。

这时候,如果你对上面的思路清楚了,那么我们就可以想象下:

  1. 上面我们是对每次的数组进行了累加。
  2. 最终我们依靠 minSum 获取最终结果。

那么,我们能不能减少变量,优化思路,从而获取更优解?

动态规划

const minimumTotal = (triangle) => {
  for (let i = triangle.length - 2; i >= 0; i--) {
    for (let j = 0; j < triangle[i].length; j++) {
      triangle[i][j] = Math.min(
        triangle[i + 1][j],
        triangle[i + 1][j + 1],
      ) + triangle[i][j];
      console.log('------');
      console.log(triangle);
    }
  }
  return triangle[0][0];
};

先看一下打印情况:

[
     [-1],
    [3,2],
  [-3,1,-1],
]
------
[ [ -1 ], [ 0, 2 ], [ -3, 1, -1 ] ]
------
[ [ -1 ], [ 0, 1 ], [ -3, 1, -1 ] ]
------
[ [ -1 ], [ 0, 1 ], [ -3, 1, -1 ] ]

可以看到,我们自底向上开始,每层进行累加,将最终结果累加到 triangle[0][0] 中。

这样,我们就逐步完善了我们的代码。

四 统计分析

本题不需要统计分析。

五 套路分析

本题暂未发现任何套路,如果有但是 jsliang 后面发现了的话,会在 GitHub 进行补充。

知识共享许可协议
jsliang 的文档库梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。
基于https://github.com/LiangJunrong/document-library上的作品创作。
本许可协议授权之外的使用权限可以从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处获得。

评论区

leon
1粉丝

励志做一条安静的咸鱼,从此走上人生巅峰。

0

0

4

举报