作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/minimum-path-sum/description/

题目描述

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

Example:

Input:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.

题目大意

求一个矩阵从左上角到右下角的最短路径和。

解题方法

第一感觉是dfs,但是题目没有说范围,估计会超时。然后就想到了DP。

使用DP创建了一个path数组,和grid数组是一样的。path代表了从左上角开始到某个点的最短路径。那么很容易知道,新的一个点的最短路径一定等于其上方、左方最短路径+当前的值。因此写成双重循环即可。因为要用到上方、左方的值,数组第一行和第一列会超出边框,其实只需要把这个方向设为前面的那个路径值即可。

这个算法的时间啊复杂度是O(m * n),空间复杂度是O(m * n)。

代码如下:

class Solution:
def minPathSum(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
if not grid or not grid[0]: return 0
m, n = len(grid), len(grid[0])
path = copy.deepcopy(grid)
for i in range(m):
for j in range(n):
if i == 0 and j == 0:
before = 0
elif i == 0:
before = path[i][j-1]
elif j == 0:
before = path[i-1][j]
else:
before = min(path[i-1][j], path[i][j-1])
path[i][j] = before + grid[i][j]
return path[m-1][n-1]

发现path数组没有必要重新复制出来,可以直接使用grid代表了。这样实际上就对grid进行了一个覆盖:遍历过的地方代表path,还没遍历到的地方代表grid。

这个算法的时间复杂度是O(m * n),空间复杂度是O(1)。由于少了复制数组的一步,事实上真的变快了。

class Solution:
def minPathSum(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
if not grid or not grid[0]: return 0
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if i == 0 and j == 0:
before = 0
elif i == 0:
before = grid[i][j-1]
elif j == 0:
before = grid[i-1][j]
else:
before = min(grid[i-1][j], grid[i][j-1])
grid[i][j] = before + grid[i][j]
return grid[m-1][n-1]

二刷的时候使用的C++,方法仍然是动态规划,第一行的每个状态等于左边状态+当前位置,和第一列的每个状态等于上边状态+当前位置。其余位置等于上边和左边的状态最小值加上当前位置。

C++代码如下:

class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
const int M = grid.size(), N = grid[0].size();
vector<vector<int>> dp(M, vector<int>(N, 0));
dp[0][0] = grid[0][0];
for (int i = 1; i < M; ++i)
dp[i][0] = dp[i - 1][0] + grid[i][0];
for (int j = 0; j < N; ++j)
dp[0][j] = dp[0][j - 1] + grid[0][j];
for (int i = 1; i < M; ++i) {
for (int j = 1; j < N; ++j) {
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[M - 1][N - 1];
}
};

参考资料:

日期

2018 年 9 月 11 日 —— 天好阴啊
2018 年 12 月 29 日 —— 2018年剩余电量不足1%

【LeetCode】64. Minimum Path Sum 解题报告(Python & C++)的更多相关文章

  1. LeetCode: Minimum Path Sum 解题报告

    Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to b ...

  2. leetCode 64.Minimum Path Sum (最短路) 解题思路和方法

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  3. [LeetCode] 64. Minimum Path Sum 最小路径和

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  4. LeetCode 64. Minimum Path Sum(最小和的路径)

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  5. LeetCode 64 Minimum Path Sum

    Problem: Given a m x n grid filled with non-negative numbers, find a path from top left to bottom ri ...

  6. C#解leetcode 64. Minimum Path Sum

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  7. [leetcode]64. Minimum Path Sum最小路径和

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  8. [leetcode] 64. Minimum Path Sum (medium)

    原题 简单动态规划 重点是:grid[i][j] += min(grid[i][j - 1], grid[i - 1][j]); class Solution { public: int minPat ...

  9. leecode 每日解题思路 64 Minimum Path Sum

    题目描述: 题目链接:64 Minimum Path Sum 问题是要求在一个全为正整数的 m X n 的矩阵中, 取一条从左上为起点, 走到右下为重点的路径, (前进方向只能向左或者向右),求一条所 ...

随机推荐

  1. 关于vim复制剪贴粘贴命令的总结-转

    最近在使用vim,感觉很好很强大,但是在使用复制剪切粘贴命令是,碰到了一些小困惑,网上找了一些资料感觉很不全,讲的也不好,遂自己进行实践并总结了. 首先是剪切(删除): 剪切其实也就顺带删除了所选择的 ...

  2. 业务逻辑审批流、审批流、业务、逻辑、面向对象、工作方式【c#】

    ------需求分析:--------1.先按照实际线下流程说这是什么事情,实际要干什么.2.再转换为面向对象-页面的操作流程,演示demo3.再与相关人员沟通是否可行需要什么地方修正.4.最终:线上 ...

  3. C#多个标题头合并

    protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e) { switch (e.Row.RowType) ...

  4. Swift-技巧(十一)重写运算符

    摘要 基础数据的运算可以直接使用四则运算符.在 Swift 中也可以通过重写四则运算符的方式,让 struct 或者 class 创建的结构体或者对象也能像基础数据那样直接使用四则运算符. Swift ...

  5. 日常Java 2021/9/20

    Java随机数 运用Java的random函数实现猜数字游戏 随机产生一个1-50之间的数字,然后让玩家猜数,猜大猜小都给出提示,猜对后游戏停止 package pingchangceshi; imp ...

  6. 容器之分类与各种测试(三)——queue

    queue是单端队列,但是在其实现上是使用的双端队列,所以在queue的实现上多用的是deque的方法.(只要用双端队列的一端只出数据,另一端只进数据即可从功能上实现单端队列)如下图 例程 #incl ...

  7. 技术预演blog

    canal整合springboot实现mysql数据实时同步到redis spring+mysql集成canal springboot整合canal监控mysql数据库 SpringBoot cana ...

  8. CentOS6设置Django开发环境

    今天在我的Centos6.5机器上安装 Django 开发环境,在安装完使用 "django-admin.py startproject myapp" 创建应用的时候报了下面的错误 ...

  9. Playing with Destructors in C++

    Predict the output of the below code snippet. 1 #include <iostream> 2 using namespace std; 3 4 ...

  10. redis入门到精通系列(九):redis哨兵模式详解

    (一)哨兵概述 前面我们讲了redis的主从复制,为了实现高可用,会选择一台服务器作为master,多台服务器作为slave.现在有这样一种情况,master宕机了,这时系统会选择一台slave作为m ...