LeetCode 63. Unique Paths II--二维数组从左上角到右下角的唯一路径的种数有多少,有1的位置不能走,只能向右或向下移动--2D DP

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).

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.

Note: m and n will be at most 100.

Example 1:

Input:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:
1. Right -> Right -> Down -> Down
2. Down -> Down -> Right -> Right

方法1:仍然在原二维数组存储,没有开辟新的数组

public class Leetcode_63_Unique_Paths_II {
    public static void main(String[] args) {
/*        int[][] obstacleGrid = new int[][]{
                {0, 0, 0, 0},
                {0, 1, 0, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0}};
        */
        int[][] obstacleGrid = new int[][]{
                {0, 0, 0,},
                {0, 1, 0},
                {0, 0, 0,}};

        System.out.println(new Leetcode_63_Unique_Paths_II().
                uniquePathsWithObstacles(obstacleGrid));
    }

    public int uniquePathsWithObstacles(int[][] obstacleGrid) {

        //如果开头的左上角是1,则无法继续,直接返回0
        if (obstacleGrid != null && obstacleGrid[0][0] == 1) {
            return 0;
        }

        //把第一行从0更新为1,如果该元素是1,则该行之后的元素(右边的元素)都不可达,都需要设置为0
        for (int i = 0; i < obstacleGrid[0].length; ) {
            if (obstacleGrid[0][i] == 0) {
                obstacleGrid[0][i] = 1;
                i++;
            } else if (obstacleGrid[0][i] == 1) {
                for (; i < obstacleGrid[0].length; i++) {
                    obstacleGrid[0][i] = 0;
                }
            }
        }

//        for (int i = 0; i < obstacleGrid.length; ) {//[0,0]已经从0变为1,所以此时要从第二行开始往下
        //把第一列从0更新为1,如果该元素是1,则该列之后的元素(下边的元素)都不可达,都需要设置为0
        for (int i = 1; i < obstacleGrid.length; ) {
            if (obstacleGrid[i][0] == 0) {
                obstacleGrid[i][0] = 1;
                i++;
            } else if (obstacleGrid[i][0] == 1) {
                for (; i < obstacleGrid.length; i++) {
                    obstacleGrid[i][0] = 0;
                }
            }
        }

        for (int row = 1; row < obstacleGrid.length; row++) {
            for (int column = 1; column < obstacleGrid[0].length; column++) {
                if (obstacleGrid[row][column] == 1) {
                    obstacleGrid[row][column] = 0;//如果不可达,则元素需设置为0
                } else {
                    obstacleGrid[row][column] = obstacleGrid[row - 1][column] + obstacleGrid[row][column - 1];
                }
            }
        }
        return obstacleGrid[obstacleGrid.length - 1][obstacleGrid[0].length - 1];
    }//uniquePathsWithObstacles
}

LeetCode 63. Unique Paths II--二维数组从左上角到右下角的唯一路径的种数有多少,有1的位置不能走,只能向右或向下移动--2D DP_第1张图片

方法2(不太好懂):用一维数组存储中间值,开辟了新的数组

/**
 * @Desc
 * @Author liuyazhou
 * @CreateTime 2018/11/18 17:46
 **/
public class LeetCode_63_UniquePathsII {

    public static void main(String[] args) {
        int[][] obstacleGrid = new int[][]{{0, 0, 0}, {0, 1, 0}, {0, 0, 0}};
        System.out.println(new LeetCode_63_UniquePathsII().uniquePathsWithObstacles(obstacleGrid));//2

        obstacleGrid = new int[][]{{0}};
        System.out.println(new LeetCode_63_UniquePathsII().uniquePathsWithObstacles(obstacleGrid));//1

        obstacleGrid = new int[][]{{1}};
        System.out.println(new LeetCode_63_UniquePathsII().uniquePathsWithObstacles(obstacleGrid));//0

    }

    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int c = obstacleGrid[0].length;//列数
        int[] dp = new int[c];
        dp[0] = 1;//别忘了初始化
        for (int[] rows : obstacleGrid) {
            for (int j = 0; j < c; j++) {
                if (rows[j] == 1) {
                    dp[j] = 0;
                } else if (j > 0) {
                    dp[j] = dp[j] + dp[j - 1];
                }
            }
        }
        return dp[c - 1];
    }


/*    public int uniquePathsWithObstacles2(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[] dp = new int[n + 1];
        dp[1] = 1;
        for (int i = 0; i < m ; i++) {
            for (int j = 1; j <=n; j++) {
                if(obstacleGrid[i][j-1] == 1){
                    dp[j] = 0;
                }else {
                    dp[j] += dp[j -1];
                }
            }
        }
        return dp[n];
    }*/


}
More explanation:
This is a typical 2D DP problem, we can store value in 2D DP array,
but since we only need to use value at dp[i - 1][j] and dp[i][j - 1] to update dp[i][j],
we don't need to store the whole 2D table, but instead store value in an 1D array, and update data by using dp[j] = dp[j] + dp[j - 1],
(where here dp[j] corresponding to the dp[i - 1][j]) and dp[j - 1] corresponding to the dp[i][j - 1] in the 2D array)

LeetCode 63. Unique Paths II--二维数组从左上角到右下角的唯一路径的种数有多少,有1的位置不能走,只能向右或向下移动--2D DP_第2张图片

LeetCode 62. Unique Paths--二维数组从左上角到右下角的唯一路径的种数有多少,只能向右或向下移动--DP

你可能感兴趣的:(Java,算法)