题目
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?
我的想法
brute force
毫无悬念的超时
class Solution {
public int uniquePaths(int m, int n) {
return pathHelper(0, m-1, n-1, 0);
}
private int pathHelper(int right, int m, int n, int down) {
if(right == m && down == n) return 1;
if(right > m || down > n) return 0;
return pathHelper(right+1, m, n, down) + pathHelper(right, m, n, down+1);
}
}
DP
居然想出来了!!!!
这里因为有向右和向下两个变量,因此定义二维数组dp[i][j]
用以存储向下走i
步向右走j
步有多少种情况
因为一次只能走一步,并且只能是向右走或者向下走一步,因此要想达i、j
到只有两种情况。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];
if(m == 1 && n == 1) return 1;
for(int k = 1; k < m; k++) {
dp[k][0] = 1; //给边界赋值
}
for(int k = 1; k < n; k++) {
dp[0][k] = 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];
}
}
没想出带存储的brute force该怎么写。。。。
个人觉得这道题应该可以用数学中的排列组合来做,好像是叫插空问题?
解答
leetcode solution 1: DP
别人的写法更加简练
public class Solution {
public int uniquePaths(int m, int n) {
int[][] grid = new int[m][n];
for(int i = 0; i<m; i++){
for(int j = 0; j<n; j++){
if(i==0||j==0) //处理边界问题
grid[i][j] = 1;
else
grid[i][j] = grid[i][j-1] + grid[i-1][j];
}
}
return grid[m-1][n-1];
}
}
//另一种更加聪明的写法
//因为需要的只是(m,n),只需要m和n中有一个变量记录下来即可
public class Solution {
public int uniquePaths(int m, int n) {
int[] arr = new int[m];
for (int i = 0; i < m; i++) {
arr[i] = 1;
}
for (int i = 1; i < n; i++) { //i-1的值不需要记录,只是用来推i的值
for (int j = 1; j < m; j++) {
arr[j] = arr[j] + arr[j-1];
}
}
return arr[m-1];
}
}
leetcode solution 2: Memoization
为何感觉与DP无异?不过是DP用的iteration这里用的recursion
class Solution {
public int uniquePaths(int m, int n) {
return uniquePathsHelper(m - 1, n - 1, new int[n][m]);
}
private int uniquePathsHelper(int m, int n, int[][] memo) {
if (m < 0 || n < 0) {
return 0;
}
else if (m == 0 || n == 0) {
return 1;
}
else if (memo[n][m] > 0) {
return memo[n][m];
}
else {
memo[n][m] = uniquePathsHelper(m - 1, n, memo) + uniquePathsHelper(m, n - 1, memo);
return memo[n][m];
}
}
}