博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode-64. 最小路径和
阅读量:4919 次
发布时间:2019-06-11

本文共 3337 字,大约阅读时间需要 11 分钟。

题目描述

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例:

输入:

[[1,3,1],
[1,5,1],
[4,2,1]]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

思路

以输入为 3*3 的网格为例,其中 m=3,n=3

[1,3,1]
[1,5,1]
[4,2,1]
由于每次只能向下或者向右移动,则坐标(0,0)的最小路径就等于当前节点加上(0,1)或(1,0)的最小值,这样可以得到递归方程:
dp(0,0) = grid(0,0) + min(dp(1,0),dp(0,1))
当到达网格的边界时,下一步只能往右走或者往下走。这样可以得到这个问题的一般递归解法。

一般递归解法

class Solution {public:    int minPathSum(vector
>& grid) { return minPathSumRecusion(grid, 0, 0); }private: int minPathSumRecusion(vector
>& grid, int m, int n){ if(grid.size() == 0) return 0; if(m == grid.size()-1 && n == grid[0].size()-1) return grid[m][n]; if(m == grid.size()-1) return grid[m][n]+minPathSumRecusion(grid,m,n+1); if(n == grid[0].size()-1) return grid[m][n]+minPathSumRecusion(grid,m+1,n); return grid[m][n]+ min(minPathSumRecusion(grid,m+1,n), minPathSumRecusion(grid,m,n+1)); }};

在leetcode上提交之后,不出意外的又超时了。下面先进行记忆化搜索进行优化,再进行动态规划算法的改写。

记忆化搜索递归

在得到一般递归解法后进行记忆化搜索的步骤一般比较固定,先建立每一步的索引表,然后初始化边界情况,然后在递归函数中判断索引表中的数据是否存在,如果存在则直接取出作为本次递归的值,不存在则继续进行下一步递归,递归返回时填写索引表中的相应值。

这个问题比较特殊的地方在于边界情况有稍许复杂:

  • grid为0的情况
  • 下一步只能往右的情况
  • 下一步只能往下的情况
class Solution {public:    int minPathSum(vector
>& grid) { if(grid.size() == 0) return 0; int m = grid.size(); int n = grid[0].size(); m_memo = vector
>(m+1,vector
(n+1,0)); //初始化边界情况 for(int i = n-1; i >= 0;--i) m_memo[m-1][i] = grid[m-1][i] + m_memo[m-1][i+1]; for(int j = m-1; j >= 0;--j) m_memo[j][n-1] = grid[j][n-1] + m_memo[j+1][n-1]; return minPathSumRecusion(grid, 0, 0); }private: int minPathSumRecusion(vector
>& grid, int m, int n){ if(grid.size() == 0) return 0; if(m_memo[m][n] != 0) { return m_memo[m][n]; } if(m == grid.size()-1 && n == grid[0].size()-1) { m_memo[m][n] = grid[m][n]; return m_memo[m][n]; } if(m == grid.size()-1) { return m_memo[m][n]; } if(n == grid[0].size()-1) { return m_memo[m][n]; } m_memo[m][n] = min(grid[m][n]+minPathSumRecusion(grid,m+1,n), grid[m][n]+minPathSumRecusion(grid,m,n+1)); return m_memo[m][n]; } vector
> m_memo;};

动态规划

按照上面的递归公式和记忆化搜索算法,如果把递归算法从(0,0)逐步递归得到(m,n)看作是自顶向下,那么从(m,n)开始通过循环逐步得到(0,0)就可以看作是自底向上,我们可以进一步得出此题的动态规划解法。

class Solution {public:    int minPathSum(vector
>& grid) { if(grid.size() == 0) return 0; int m = grid.size(); int n = grid[0].size(); m_memo = vector
>(m+1,vector
(n+1,0)); //初始化边界情况 for(int i = n-1; i >= 0;--i) m_memo[m-1][i] = grid[m-1][i] + m_memo[m-1][i+1]; for(int j = m-1; j >= 0;--j) m_memo[j][n-1] = grid[j][n-1] + m_memo[j+1][n-1]; for(int i = m-2; i >= 0;--i) { for(int j = n-2; j >= 0;--j) { m_memo[i][j] = grid[i][j] + min(m_memo[i][j+1], m_memo[i+1][j]); } } return m_memo[0][0]; }};

转载于:https://www.cnblogs.com/BlueskyRedsea/p/9261412.html

你可能感兴趣的文章
C++ 小笔记
查看>>
Mysql 语句优化
查看>>
例子:进度条
查看>>
包含单引号的sql
查看>>
HTML 基础 2
查看>>
Java 最常见 200+ 面试题全解析:面试必备(转载)
查看>>
LinkedList
查看>>
Spring框架下PropertyPlaceholderConfigurer类配置roperties文件
查看>>
SQL查询优化
查看>>
使用子查询
查看>>
SD卡调试关键点
查看>>
Hadoop HBase Phoenix 版本
查看>>
深入Java集合学习系列:ConcurrentHashSet简单实现
查看>>
[原创]独立模式安装Hive
查看>>
Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1
查看>>
LeetCode My Solution: Minimum Depth of Binary Tree
查看>>
Objective-C中的Category(分类)
查看>>
浅谈python可迭代对象,迭代器
查看>>
python 多分类任务中按照类别分层采样
查看>>
Java(23)_ String类常用方法
查看>>