LeetCode-62. 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?
LeetCode-62. Unique Paths_第1张图片

Above is a 3 x 7 grid. How many possible unique paths are there?

Note: m and n will be at most 100.

题目是求从左上角有多少条路径可以走到右下角。每次只能向下走或者是向右走。

人生中第一次使用动态规划,以前都不敢去涉及该类的题目=。=
虽然这道题及其简单。在此也比较下动态规划与记忆化搜索的区别。

动态规划法

动态规划(dynamic programming),与“分治思想”有些相似,都是将问题划分成子问题,并通过合并子问题的解来获得整个问题的解。与“分治”的不同之处在于,对于一个相同的子问题动态规划算法不会计算第二次,其实现原理是将每一个计算过的子问题的值保存在一个表中。

LeetCode-62. Unique Paths_第2张图片

如上图所示,Finish 所在的行与列都只有一条路径走到Finish。(只能一直向下/右走)
状态转移方程(起这种名字让我这种菜鸟如何理解呢?):
dp[i][j] = dp[i + 1][j] + dp[i][j + 1];

dp[i][j] 表示从[i, j]所在的方块有多少条路径到达 Finish

    public int uniquePathsDP(int m, int n) {
        if (n == 1 || m == 1) {
            return 1;
        }
        int[][] dp = new int[m][n];
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                if (i == m - 1 || j == n - 1) {
                    dp[i][j] = 1;
                }
                if (i + 1 < m && j + 1 < n) {
                    dp[i][j] = dp[i + 1][j] + dp[i][j + 1];
                }
            }
        }
//        System.out.println(Arrays.deepToString(dp));
        return dp[0][0];
    }

记忆化搜索

class Solution {
    private int[][] dp = new int[105][105];
    private int m;
    private int n;

    private int DFS(int i, int j) {

        if (i == m - 1 && j == n - 1) {
            return 1;
        }

        if (i >= m || j >= n) {
            return 0;
        }

        if (dp[i][j] != 0) {
            return dp[i][j];
        }


        dp[i + 1][j] = DFS(i + 1, j);
        dp[i][j + 1] = DFS(i, j + 1);
        dp[i][j] = dp[i + 1][j] + dp[i][j + 1];

        return dp[i][j];
    }

    public int uniquePaths(int m, int n) {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                dp[i][j] = 0;
            }
        }

        this.m = m;
        this.n = n;
        return DFS(0, 0);
    }
}

区别

  1. DP 是从下向上,而记忆化搜索是从上向下
  2. 使用 DP 为了求到最终结果需要把过程中所有的局部结果都保存下来,以便下一步可能会使用
  3. 记忆化搜索使用递归实现的,而递归的回退过程(保存局部结果)就相当于DP了。

这样一来 DP 在时间上几乎总是优于记忆化搜索的,毕竟多了很多的函数调用。

你可能感兴趣的:(leetcode题解)