Question
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?
本题难度Medium。有3种算法分别是:DFS、DP和一维数组(DP优化版)
1、DFS
【复杂度】
时间 O(N!) 空间 O(1)
【思路】
利用DFS遍历所有可能。不过这个方法会 Time Limit Exceeded。
【注意】
23行helper(x+1,y,m,n);
不要写成:
helper(++x,y,m,n);
它会影响25行。
【代码】
public class Solution {
int count=0;
public int uniquePaths(int m, int n) {
//require
if(m==0||n==0)
return 1;
if(m==1||n==1)
return 1;
//invariant
helper(0,0,m,n);
//ensure
return count;
}
private void helper(int x,int y,int m,int n){
//base case
if(x==m-1||y==n-1){
count++;
return;
}
if(x<m-1)
helper(x+1,y,m,n);
if(y<n-1)
helper(x,y+1,m,n);
}
}
2、DP
【复杂度】
时间 O(MN) 空间 O(MN)
【思路】
每一步只能向右方或者下方走,所以经过每一个格子路径数只可能源自左方或上方,这就得到了动态规划的递推式,我们用一个二维数组dp储存每个格子的路径数,则dp[i][j]=dp[i-1][j]+dp[i][j-1]
。最左边和最上边的路径数都固定为1,代表一直沿着最边缘走的路径。
【附】
本题的测试用例中应该没有m=0,n=0
。
【代码】
public class Solution {
public int uniquePaths(int m, int n) {
//require
int[][] dp=new int[m][n];
for(int i=0;i<m;i++)
dp[i][0]=1;
for(int i=0;i<n;i++)
dp[0][i]=1;
//invariant
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];
//ensure
return dp[m-1][n-1];
}
}
3、一维数组
【复杂度】
时间 O(MN) 空间 O(N)
【思路】
实际上我们可以复用每一行的数组来节省空间,每个元素更新前的值都是其在二维数组中对应列的上一行的值。这里dp[i] = dp[i - 1] + dp[i]
【注意】
dp[0]一直等于1,因此8行的i
与9行的j
都是从1
而不是0
开始循环。
【代码】
public class Solution {
public int uniquePaths(int m, int n) {
//require
int[] dp=new int[n];
for(int i=0;i<n;i++)
dp[i]=1;
//invariant
for(int i=1;i<m;i++)
for(int j=1;j<n;j++)
dp[j]=dp[j]+dp[j-1];
//ensure
return dp[n-1];
}
}
参考
[Leetcode] Unique Paths 唯一路径