Minimum Path Sum

Unique Paths

 

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

How many possible unique paths are there?


深度搜索备忘录法:

class Solution {
public:
    vector > f;
    int uniquePaths(int m, int n) {
        if(m <= 0 || n <= 0)
            return -1;
		f = vector > (m, vector(n,-1));
        return dfs(m-1,n-1);
    }
    
    int dfs(int m, int n)
    {
        if(m == 0 || n == 0)
            return 1;
        return getOrupdate(m-1, n ) + getOrupdate(m, n-1);
    }

	int getOrupdate(int m, int n)
	{
		if(m < 0 || n < 0)
			return 0;
		if(f[m][n] > 0 )
			return f[m][n];
		else 
			return f[m][n] = dfs(m,n);
	}
};


动态规划:
class Solution {
public:
   //动态规划,
    int uniquePaths(int m, int n) {
        if(m <= 0 || n <= 0)
            return -1;
		vector > f(m, vector(n,0));
		for(int i = 0; i < m ; ++i)//边界,第一行第一列就是一步就到
		    f[i][0] = 1;
		for(int i = 0; i < n ; ++i)
		    f[0][i] = 1;
		    
		for(int i = 1; i < m ; ++i)
		    for(int j = 1; j < n; ++ j)
		        f[i][j] = f[i-1][j] + f[i][j-1];
		
		return f[m-1][n-1];
    }
    
    
};

动态规划,滚动数组

class Solution {
public:
   //动态规划,滚动数组
    int uniquePaths(int m, int n) {
        if(m <= 0 || n <= 0)
            return -1;
		vector  f(n,0);
		f[0] = 1;
		    
		for(int i = 0; i < m ; ++i)
		    for(int j = 1; j < n; ++ j)
		        f[j] = f[j] + f[j-1];
//左边的f[j]是需要求解的值f[i][j],右边的f[j]是f[i-1][j],f[j-1]是f[i][j-1],,
return f[n-1]; }};
 
  


Unique Paths 

II


Follow up for "Unique Paths":

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,

There is one obstacle in the middle of a 3x3 grid as illustrated below.

[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]

class Solution {
public:
    vector > f;
    int uniquePathsWithObstacles(vector > &obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        if(m <= 0 || n <= 0)
            return -1;
		f = vector > (m, vector(n,-1));
        return dfs(obstacleGrid, m-1,n-1);
    }
    int dfs(vector > &obstacleGrid,int m, int n)
    {
        if(obstacleGrid[m][n])
            return 0;
        if(m == 0 && n == 0)
            return 1;
        return getOrupdate(obstacleGrid,m-1, n ) + getOrupdate(obstacleGrid, m, n-1);
    }

	int getOrupdate(vector > &obstacleGrid, int m, int n)
	{
		if(m < 0 || n < 0)
			return 0;
		if(f[m][n] > 0 )
			return f[m][n];
		else 
			return f[m][n] = dfs(obstacleGrid,m,n);
	}
};

滚动数组:

class Solution {
public:
   
    int uniquePathsWithObstacles(vector > &obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        if(m <= 0 || n <= 0)
            return -1;
		if(obstacleGrid[0][0] || obstacleGrid[m-1][n-1])
		    return 0;
		vector f(n, 0);
		f[0] = 1;
		
		for(int i = 0; i < m; ++ i)
		    for(int j = 0; j < n; ++ j)//知道为什么j从0开始了,因为除了f[0][0]判断了不是障碍,后面的第一列可能存在障碍
		    {
		        if(obstacleGrid[i][j])
		            f[j] = 0;
		        else if ( j == 0)//障碍物可能在第一列,这样子需要注意f[0]的更新,
		      //不对是因为第一列只有一个方向可以到达,如果,他前面那步已经是0,当前位置不可能f[j] = 1,滚动数组保持之前的值f[j] = f[j]
		            f[j] = f[j];
		        else if(j > 0)
		            f[j] = f[j-1] + f[j];
		    }
        return f[n-1];
    }
    
};


Minimum Path Sum

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.

深度搜索,备忘录法

class Solution {
public:
   
    vector > f;
    
    //备忘录法,把每次计算的值保存下来
    int getOrupdate(vector > &grid, int m, int n)
    {
        if(m < 0 || n < 0)
            return INT_MAX;
        if(f[m][n] > 0)
            return f[m][n];
        else
            return f[m][n] = dfs(grid, m, n);
    }
    
    int dfs(vector > &grid, int m, int n)
    {
        if(m == 0 && n == 0 )
            return grid[0][0];
        
        return min(getOrupdate(grid,m-1,n), getOrupdate(grid,m,n-1)) + grid[m][n];
    }
    int minPathSum(vector > &grid) {
        if(grid.size() == 0)
            return -1;
        int m = grid.size();
        int n = grid[0].size();
        f=vector > (m, vector (n,-1));//注意初始化的形式,f(m, vector (n,-1))不对,只能在声明的时候这样子
        return dfs(grid, m-1, n-1);//实际应该小1
         
    }
    
    
};

动态规划

空间复杂度O(MN),状态函数:f[i][j] = min(f[i][j-1], f[i-1][j]) + grid[i][j];

class Solution {
public:
   
    int minPathSum(vector > &grid) {
        if(grid.size() == 0)
            return -1;
        int m = grid.size();
        int n = grid[0].size();
        vector > f(m, vector(n,0));
        f[0][0] = grid[0][0];
        for(int i = 1; i < m; ++ i)
        {
            f[i][0] = f[i-1][0] + grid[i][0];//第一列的元素递增
        }
        for(int i = 1; i < n; ++ i)
        {
            f[0][i] = f[0][i-1] + grid[0][i];//第一行的元素递增
        }
        for(int i = 1 ; i < m ; ++ i)
            for(int j = 1; j < n; ++ j)
            {
                f[i][j] = min(f[i][j-1], f[i-1][j]) + grid[i][j];
            }
        return f[m-1][n-1];   
    }
};



滚动数组的解法:
class Solution {
public:
   
    int minPathSum(vector > &grid) {
        if(grid.size() == 0)
            return -1;
        int m = grid.size();
        int n = grid[0].size();
        vector f(n,INT_MAX);
        f[0] = 0;
        for(int i = 0 ; i < m ; ++ i)
        {
            f[0] += grid[i][0];//用的是第一列的累加,作为滚动数组的起始值
            for(int j = 1; j < n; ++ j)//总体看是二维,可以简化成一维,对数组中剩下的值,不断更新的结果
            {
                //左边的f[j]是需要求解的值f[i][j],右边的f[j]是f[i-1][j],f[j-1]是f[i][j-1],所以初始化需要是最大值,
                f[j] = min(f[j-1], f[j]) + grid[i][j];
            }
        }
        return f[n-1];   
    }
};


你可能感兴趣的:(leetcode)