62. Unique Paths

yPhantom 2019年11月08日 25次浏览

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?

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

Note: m and n will be at most 100.

Example 1:

Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Right -> Down
2. Right -> Down -> Right
3. Down -> Right -> Right

Example 2:

Input: m = 7, n = 3
Output: 28

Solution

这道题是最为基础的动态规划题,可以很清楚的看出其转移方程为

dp[i][j] = dp[i-1][j] + dp[i][j - 1]

但是想要写出最完美的解法还是有点难度的。

我们可以轻松的写出如下的答案

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        dp[0][0] = 1;
        for (int i = 1; i < m; i++) {
            dp[i][0] = 1;
        }
        for (int j = 1; j < n; j++) {
            dp[0][j] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[m - 1][n - 1];
    }
}

注:Arrays.fill只能赋值一维数组,如果赋值两维数组,则都会引用同一个数组。该函数内部就是用for循环实现的,因此不如直接用for循环

此时的时间复杂度是O(mn),空间复杂度是O(mn)。

仔细观察这个转移方程,发现实际上仅仅是三个数值的计算,我们可以看成是两个一维数组在计算,看成是两行(两列)在计算。

class Solution {
    public int uniquePaths(int m, int n) {
        int[] cur = new int[n];
        int[] pre = new int[n];
        for (int i = 0; i < n; i++) {
            cur[i] = 1;
            pre[i] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                cur[j] = cur[j - 1] + pre[j];
            }
            int[] tmp = pre;
            pre = cur;
            cur = tmp;
        }
        return pre[n - 1];
    }
}

此时,时间复杂度是O(mn),空间复杂度是O(2n)。

接着,我们再仔细看看,cur和pre实际上用一个数组就可以完成。

class Solution {
    public int uniquePaths(int m, int n) {
        int[] cur = new int[n];
        for (int i = 0; i < n; i++) {
            cur[i] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                cur[j] = cur[j - 1] + cur[j];
            }
        }
        return cur[n - 1];
    }
}