给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。java
**说明:**每次只能向下或者向右移动一步。算法
示例:数组
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 由于路径 1→3→1→1→1 的总和最小。
复制代码
昨天作了道算法题,感受画图颇有助于本身理解算法的过程,此次再挑一个算法加深印象。碰到这种类型的题目,和递归很像,可是使用递归,若是数据范围比较大,就会花费很长时间。bash
动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,经过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划经常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间每每远少于朴素解法。数据结构
废话少说性能
根据题意,到达网格中的某个点最短,能够理解为网格中的任何一个点都是能够走过去的,并且任何一个网格都有一个最短的路径。测试
那么咱们使用一种数据结构保存,从顶点到达网格中任意一点的最短位置。根据人的正常逻辑,画图以下:spa
根据上面的图片能够了解:3d
点
处于第一行的时候,它的最短路径就是同一行的前一个位置加上当前位置点
处于第一列的时候,它的最短路径就是上一行的位置加上当前位置点
处于顶点的时候,它就是顶点的值点
位于中间的位置,它是其上一行或上一列的最小值加上当前的值至此,咱们写程序以下:code
public static int minPathSumAi(int[][] grid){
// 特殊状况处理
if (grid.length == 0){
return 0;
}
// 新建一个标记数组,标记到每一个位置的最短路径
int xLen = grid.length;
int yLen = grid[0].length;
int[][] markBit = new int[xLen][yLen];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
// 初始位置
if (i == 0 && j == 0){
markBit[i][j] = grid[i][j];
}
// 当点在第一行的位置时
else if (i == 0){
markBit[i][j] = markBit[i][j-1] + grid[i][j];
}
// 当点在第一列的位置时
else if (j == 0){
markBit[i][j] = markBit[i-1][j] + grid[i][j];
}
// 当点在数组的中间位置时
else {
markBit[i][j] = Math.min(markBit[i-1][j] , markBit[i][j-1]) + grid[i][j];
}
}
}
return markBit[xLen-1][yLen-1];
}
复制代码
而后到LeetCode上测试,性能有待于提高,后续水平提升以后再想更优的方案吧,目前先理解解题方式。
程序的运行都是人控制的,在程序运行以前,确保你本身的逻辑清晰,画图能够帮你理清逻辑。