【LeetCode刷题笔记】动态规划(三)

64. 最小路径和

解题思路:
  • 1. DFS 从上往下【超时】 ,定义递归函数 dfs(grid, i,  j, path) 每次递归中 使用 path 收集(累加)沿途遇到的节点值,然后 按照 往下 走和 往右 走进行两路递归调用,dfs(grid, i + 1,  j, path + grid[i][j])dfs(grid, i,  j + 1, path + grid[i][j]) 注意往下走和往右走的时候判断下标未越界才继续。
  • 递归终止 i == M - 1 && j == N - 1 到达右下角时 更新答案取 res path 最小值

解题思路:
  • 2. DFS + 记忆优化 ,自底向上,递归函数返回从  [i, j]  位置出发达到右下角 [M - 1, N - 1] 的最小路径和。
  • 每次递归中,按照 往下 走和 往右 走进行子递归调用, dfs(grid, i + 1,  j ) dfs(grid, i,  j + 1 ) 收集返回结果,当前函数返回 min(往下走的最小路径和, 往右走的最小路径和 ) + 当前节点值 作为当前节点到右下角的最小路径和。
  • 递归终止: i == M - 1 && j == N - 1 时,即到达右下角位置,返回 右下角自身的节点值

解题思路:
  • 3.  动态规划 从右下角出发倒推 ,定义 dp[i][j] 表示从坐标 (i, j) 到右下角的最小路径和, 最终返回 dp[0][0]
  • 初始化 右下角 dp 状态值为 自身 的节点值,在 最后一行 中,只能选择 往右 走,因此 dp[i][j] = 自身节点值 + 右边一列的dp值 ,在 最后一列 中,只能选择 往下 走,因此   dp[i][j] = 自身节点值 + 下边一行的dp值
  • 对于其它位置,既可以 往右 走也可以 往下 走, dp 值取决于 min( 右边一列的dp值, 下边一行的dp值) + 自身节点值 。因此我们从倒数第二行第二列开始倒序计算剩余每个位置的 dp 值。

解题思路:
  • 4. 动态规划 从左上角出发正推, 定义 dp[i][j] 表示从 (0, 0) (i, j) 的最小路径和, 最终返回 dp[M - 1][N - 1]
  • 初始化 左上角 dp 值为 自身 , 在 第一行 中,当前位置只能由 左边一列 到达,因此 dp = 左侧一列的dp + 自身节点值 第一列 中,当前位置只能由 上边一行 到达,因此 dp = 上边一行的dp + 自身节点值
  • 然后从第二行第二列开始更新剩余位置 dp 值,剩余位置可以由 左侧 上方 到达,因此 dp = min(上方dp,左侧dp) + 自身

剑指 Offer 47. 礼物的最大价值

解题思路:
  • 同【64. 最小路径和】只不过本题是求 最大路径和 ,将求 min 的地方改成求 max 即可。

931. 下降路径最小和

解题思路:
  • 1. 动态规划 自底而上 ,定义 dp[i][j] 表示从元素 [i, j] 出发的下降路径最小和, 最终返回 dp 数组里 第一行 中的 最小dp值
  • 初始化 最后一行 dp 值为 自身 ,然后从从 倒数第2行 开始计算其余位置 dp 值。
  • 因为是 从下往上 求解的,所以如果是 最左边一列 ,只能由 下方 右下方 位置到达,因此 dp = min(下方dp, 右下方dp) + 当前节点值 。 同样,如果是 最右边一列 ,只能由 下方 左下方 位置到达 ,因此 dp = min(下方dp, 左下方dp) + 当前节点值
  • 其他位置,可以 下方 左下方 右下方 三个 位置到达 ,因此 dp = min(下方dp, 左下方dp,右下方dp) + 当前节点值

1. 当前位置为最左边一列的时候

当前位置(1,0)只能由(2,0)和(2,1)得到,因此最小下降路径和取二者最小加自身,此时对应的状态转移方程:dp[i][j] = min(dp[i + 1][j],dp[i + 1][j + 1]) + matrix[i][j]

2. 当前位置为最右边一列的时候

当前位置(1,2)只能由(2,1)和(2,2)得到,因此最小下降路径和取二者最小加自身,此时对应的状态转移方程:dp[i][j] = min(dp[i + 1][j],dp[i + 1][j - 1]) + matrix[i][j]

3. 非左边和非右边的列

当前位置(1,1)的只能由(2,0),(2,1)和(2,2)得到,那么要求(1,1)处最小下降路径和,就是从这三个可选方案中,选择最小的一个加上自身的值,因此我们得到了状态转移方程:dp[i][j] = min(dp[i + 1][j], min(dp[i + 1][j + 1], dp[i + 1] [j - 1])) + matrix[i][j]

解题思路:
  • 2. 动态规划 自上而下 ,定义 dp[i][j] 表示从 第0行 [i, j] 位置的下降路径最小和, 最终返回 dp 数组里 最后一行 中的 最小dp值
  • 初始化 第一行 dp 值为 自身 ,然后从 第2行 开始计算其余位置 dp
  • 如果是 最左边一列 ,只能由 上方 右上方 到达,因此 dp = min(上方dp, 右上方dp) + 当前节点值 。如果是 最右边一列 ,只能由 上方 左上方 到达,因此 dp = min(上方dp, 左上方dp) + 当前节点值
  • 其他位置,可以由 上方 左上 右上 三个方向到达,因此 dp = min(上方dp, 左上方dp,右上方dp) + 当前节点值

 本题思路类似64,只是方向细节不同。

62. 不同路径

解题思路:
  • 1. DFS + 记忆优化 ,递归函数返回从 [i, j] 出发到右下角的路径数,每次递归中按照 往下 走和 往右 走两个方向进行递归调用(注意越界判断),将两个方向返回的路径数 相加之和 作为当前递归函数的返回值。
  • 递归终止: i == m - 1 && j == n - 1 ,即到达 右下角 时,返回 1种 路径数。

解题思路:
  • 2. 动态规划 右下角 出发 ,求 每个位置 右下角 的路径数,定义 dp[i][j] 表示从位置 [i, j] [m - 1, n - 1] 的路径数, 最终返回 dp[0][0]
  • 最后一行 最后一列 中,只能沿着 一个方向 前进,因此 dp 值是 1
  • 其他位置,可以由 右边 下方 到达,因此 dp 值是 下方 右边 dp 值相加 之和 dp[i][j] =  dp[i + 1][j] +  dp[i][j  + 1 ]

这个解法求的其实是右下角到每个位置的路径数,包括了起始位置。注意,题目求的是路径总数,因此dp值是求和,如果求的是最大路径数/最小路径数,那dp值在更新时就是比最大/最小值。

解题思路:
  • 3. 动态规划 从左上角出发 ,求 初始 位置 每个 位置 的路径数,定义  dp[i][j] 表示从位置 [0, 0] [i, j] 的路径数, 最终返回 dp[m-1][n-1]
  • 第一行 第一列 中,只能沿着 一个方向 前进, 因此 dp 值是 1
  • 其他位置,可以由 上方 左侧 位置达到,因此 dp 值是 上方 左侧
  • 19
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

川峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值