📑 题目:64. 最小路径和

🚀 本题 LeetCode 传送门

题目大意

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。说明:每次只能向下或者向右移动一步。

解题思路

  • 在地图上求出从左上角到右下角的路径中,数字之和最小的一个,输出数字和。
  • 这一题最简单的想法就是用一个二维数组来 DP,当然这是最原始的做法。由于只能往下和往右走,只需要维护 2 列信息就可以了,从左边推到最右边即可得到最小的解。更近一步,可以直接在原来的数组中做原地 DP,空间复杂度为 0 。

代码

  1. package leetcode
  2. // 解法一 原地 DP,无辅助空间
  3. func minPathSum(grid [][]int) int {
  4. m, n := len(grid), len(grid[0])
  5. for i := 1; i < m; i++ {
  6. grid[i][0] += grid[i-1][0]
  7. }
  8. for j := 1; j < n; j++ {
  9. grid[0][j] += grid[0][j-1]
  10. }
  11. for i := 1; i < m; i++ {
  12. for j := 1; j < n; j++ {
  13. grid[i][j] += min(grid[i-1][j], grid[i][j-1])
  14. }
  15. }
  16. return grid[m-1][n-1]
  17. }
  18. // 解法二 最原始的方法,辅助空间 O(n^2)
  19. func minPathSum1(grid [][]int) int {
  20. if len(grid) == 0 {
  21. return 0
  22. }
  23. m, n := len(grid), len(grid[0])
  24. if m == 0 || n == 0 {
  25. return 0
  26. }
  27. dp := make([][]int, m)
  28. for i := 0; i < m; i++ {
  29. dp[i] = make([]int, n)
  30. }
  31. // initFirstCol
  32. for i := 0; i < len(dp); i++ {
  33. if i == 0 {
  34. dp[i][0] = grid[i][0]
  35. } else {
  36. dp[i][0] = grid[i][0] + dp[i-1][0]
  37. }
  38. }
  39. // initFirstRow
  40. for i := 0; i < len(dp[0]); i++ {
  41. if i == 0 {
  42. dp[0][i] = grid[0][i]
  43. } else {
  44. dp[0][i] = grid[0][i] + dp[0][i-1]
  45. }
  46. }
  47. for i := 1; i < m; i++ {
  48. for j := 1; j < n; j++ {
  49. dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
  50. }
  51. }
  52. return dp[m-1][n-1]
  53. }