动态规划法编程小练习

编程小练习:

时间: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<vector<int>>& grid) {

        int m = grid.size();

        int n = grid[0].size();

        if(m == 0 || n == 0)

        {

            return 0;

        }

        vector<int> dp(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] <dp[j-1]) ? (dp[j] + grid[i][j]) : (dp[j-1] + grid[i][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] <dp[j]) ? (dp[j-1] + grid[i][j]) : (dp[j] + grid[i][j]);

                }

            }

        }

       

        return dp[n-1];

    }

}


猜你喜欢

转载自blog.csdn.net/xingzengji9253/article/details/80621209