编程小练习:
时间:2018.6.8
做一些算法的小练习,另外强化C++代码训练,顺便学习python和java的基本语法
LeeCode64
64. Minimum Path Sum
Given a m x n grid filled with non-negativenumbers, find a path from top left to bottom right which minimizes the sum of all numbers along itspath.
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 minimizesthe sum.
题目大意:
一个m*n的二维数组a,每个元素是一个非负数,从左上角走到右下角,每次只能朝右或朝下走,不能走出矩阵,使得经过的路径总和最小。
这道题目采用数学知识计算最多有多少种走法,分析如下:
m行n列,从左上角走到右下角,总共需要的步数为m+n-2,其中m-1步是向下走,n-1步是向右走,任意选择路径的条数,一共有C(m+n-2, m-1)种走法。
我们要在这么多种走法中选择出一条最短路径,如果用常规方法——遍历所有的路径找到最短的一条,当m和n都很大时,这样的方法非常浪费时间。
采用DP算法(动态规划法),分析如下:
1、记dp[i][j]为从左上角走到坐标(i,j)处的路径累计最小值。
2、由于规则是只能从上到下或者从左到右行走,故从左上角到达坐标(i,j)一定会经过坐标
(i,j-1)或(i-1,j)。那么:
从上面过来的累计为:dp[i][j] = dp[i-1][j] + a[i][j];
从左边过来的累计为:dp[i][j] = dp[i][j-1] + a[i][j];
求最小值,权衡得:dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + a[i][j];
3、初始化——几个特殊的位置
(1)左上角:dp[0][0] = a[0][0]
(2)上边界:dp[0][j>0] = dp[0][j-1] + a[0][j] ->直着朝右走
(3)左边界:dp[i>0][j] = dp[i-1][0] + a[i][0] ->直着朝下走
由于要遍历整个二维数组,时间复杂度为O(m*n)
另外还需要一个统计的数组dp[m][n],空间复杂度为O(m*n)。
但是发现dp[i][j]只与dp[i-1][j]和dp[i][j-1]有关,对于每个i正向循环j,之前的dp[j-1]都是新更新的,dp[j]还是旧的。当对dp[i][j](当前是dp[j])进行权衡时,那么其实就是权衡它左边值dp[i][j-1](当前是dp[j-1])和上面的值dp[i-1][j](当前是dp[j],更新之前的dp[j]),这样来确定现在需要更新的dp[j]。所以其实可以优化空间复杂度为O(n)。
下面分别用C++、python和java对其进行实现,代码如下:
一、C++
classSolution {
public:
intminPathSum(vector
int m = grid.size();
int n = grid[0].size();
if(m == 0 || n == 0)
{
return 0;
}
vector
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(i == 0)
{
if(j == 0)
{
dp[j] = grid[i][j];
}
else
{
dp[j] = dp[j-1] +grid[i][j];
}
}
else if(j == 0)
{
dp[j] = dp[j] + grid[i][j];
}
else
{
dp[j] = (dp[j] } } } return dp[n-1]; } }; 二、python3 classSolution: def minPathSum(self, grid): """ :type grid: List[List[int]] :rtype: int """ m = len(grid) n = len(grid[0]) if(m == 0 or n == 0): return 0 dp = [0]*5 for i in range(m): for j in range(n): if(i == 0): if(j == 0): dp[j] = grid[i][j] else: dp[j] = dp[j-1] +grid[i][j] elif(j == 0): dp[j] = dp[j] + grid[i][j] else: dp[j] = min(dp[j-1], dp[j])+ grid[i][j] return dp[n-1] 三、java classSolution { public int minPathSum(int[][] grid) { int m = grid.length; int n = grid[0].length; if(m == 0 || n == 0) { return 0; } int[] dp = new int[n]; for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { if(i == 0) { if(j == 0) { dp[j] = grid[i][j]; } else { dp[j] = dp[j-1] +grid[i][j]; } } else if(j == 0) { dp[j] = dp[j] + grid[i][j]; } else { dp[j] = (dp[j-1] } } } return dp[n-1]; } }