「LeetCode」931-下降路径最小和

123 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

一.题目:

931. 下降路径最小和 给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 **的 ****最小和 。

下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)(row + 1, col) 或者 (row + 1, col +1) 。

示例 1:

image.png

输入: matrix = [[2,1,3],[6,5,4],[7,8,9]]
输出: 13
解释: 如图所示,为和最小的两条下降路径

示例 2:

image.png

输入: matrix = [[-19,57],[-40,-5]]
输出: -59
解释: 如图所示,为和最小的下降路径

提示:

  • n == matrix.length == matrix[i].length
  • 1 <= n <= 100
  • -100 <= matrix[i][j] <= 100

二、思路分析:

首先,题目要求我们求出从顶部到底部的最小路径和,而每次往下走只能从正下或者对角线往下走,一直到方形的底部求出最小的路径和。对于这种问题,一般采取动态规划的思想,因为他符合动态规划要求的一切,最终结果也是需要最值问题。

  • 首先我们确立动态规划的base case,由于我们题目要求从上往下走,而且不限于从[0,0]开始走,所以我们的base case就能够确定为第一行的所有元素值,如果目标是第一行的元素直接返回元素值即可。
  • 接下来是状态转移方程,由于我们需要找到底部的最小路径和的值,而底部的路径和的值是由它的上方左上方右上方决定的,只需要找到这三个路径和的最小值即可。而这它的前三个值则是由它之前的值决定的,这就是重叠子问题最优子结构决定的。
  • 除此之外,我们需要创建一个备忘录,因为存在重叠子问题我们可以复用结果,最终我们返回的结果是要找到最后一排的任何位置,且是最小值即可。

image.png

三、代码:

/**
 * @param {number[][]} matrix
 * @return {number}
 */
var minFallingPathSum = function (matrix) {
    function dp(matrix, i, j) {
        //非法索引
        if (i < 0 || j < 0 || i >= matrix.length || j >= matrix[0].length) return 66666
        //base case 
        if (i == 0) return matrix[0][j]
        if(memo[i][j] !== 666)return memo[i][j]
        //状态转移方程
        memo[i][j] = matrix[i][j] + Math.min(dp(matrix,i-1,j-1),
        dp(matrix,i-1,j),dp(matrix,i-1,j+1))
        return memo[i][j]
    }
    //先将所有数值初始化
    let n = matrix.length
    let intialValue = 666
    let memo = new Array(n).fill(intialValue).map(() => new Array(n).fill(intialValue))
    let res = Number.MAX_SAFE_INTEGER
    //终点可能在最后一排的任何位置
    for(let j=0 ; j<n ; j++){
        res = Math.min(res,dp(matrix,n-1,j))
    }
    return res
};

四、总结:

总的来说,一般涉及最值得问题,如果里面由重叠子问题和最优子结构的结构都需要考虑利用动态规划进行求解,动态规划最重要的就是base case状态转移方程,只要明确了状态转移方程基本上动态规划就没问题了。