LeetCode62不同路径解题记录

LeetCode62.不同路径 解题感想

  • 一.题目介绍
  • 二.解题思路及代码实现
    • 方法一:深度优先搜索(dfs)
    • 方法二:记忆化搜索
    • 方法三:动态规划
    • 方法四:组合数学法
  • 总结

一.题目介绍

题目链接:LeetCode62.不同路径;

LeetCode62不同路径解题记录_第1张图片

二.解题思路及代码实现

方法一:深度优先搜索(dfs)

由于是求从一个点到另一个点的路径有多少条,显而易见,可以采用深度优先搜索的方式,遍历所有路径,如果能够到达目标坐标的路径并统计路径数目然后返回。Java代码如下:

class Solution {
    public int uniquePaths(int m, int n) {
        return dfs(m,n,1,1);
    }
    public int dfs(int m,int n,int x,int y){
        if(x==m&&y==n)
            return 1;
        if(x>m||y>n)
            return 0;
        int ans=0;
        ans+=dfs(m,n,x+1,y);
        ans+=dfs(m,n,x,y+1);
        return ans;
    }
   
}

然而很遗憾,采用深度优先搜索的方式会RE,提交结果如下:

LeetCode62不同路径解题记录_第2张图片

方法二:记忆化搜索

既然暴力搜索会超时,那么就考虑记忆化搜索:用一个数组记录已经获取到了的结果,在递归过程中如果需要某个已经计算过的值,就直接返回,否则就行递归,并将该值记录在数组的对应下表元素中。采用记忆化搜索的方法,思路简单,结构清晰,通过以空间换时间的方式,极大地减小了时间复杂度。Java代码如下:

class Solution {
    public int uniquePaths(int m, int n) {
        int[][]rec=new int[m+1][n+1];
        return dfs(m,n,1,1,rec);
    }
    public int dfs(int m,int n,int x,int y,int[][]rec){
        
        if(x==m&&y==n)
            return 1;
        if(x>m||y>n)
            return 0;
        if(rec[x][y]!=0)
            return rec[x][y];
        int ans=0;
        ans+=dfs(m,n,x+1,y,rec);
        ans+=dfs(m,n,x,y+1,rec);
        rec[x][y]=ans;
        return rec[x][y];
    }
   
}

提交结果如下:
LeetCode62不同路径解题记录_第3张图片
看样子记忆化搜索的方法还挺不错的,就是空间复杂度是O(mn).

方法三:动态规划

这道题采用动态规划也能做,由于这道题的思路很简单,可以很轻松地得到递推公式:dp[x][y]=dp[x-1][y]+dp[x][y-1],当然要注意dp数组的初始化。Java代码如下:

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

当然,由于dp[x][y]的状态只与dp[x-1][y]和dp[x][y-1]有关,所以可以用滚动数组对空间复杂度进行优化,感兴趣的朋友可以自己实现,在此不再赘述。运行结果如下:
LeetCode62不同路径解题记录_第4张图片

方法四:组合数学法

学过离散数学的朋友应该知道,本题就是组合数学中多重集的全排列问题。要从起点到达终点,需要向x轴方向走m个坐标,向y轴走n个坐标,不同的路径就对应着多重集**S={(m-1)x,(n-1)y}**的全排列问题,所以可以直接计算出答案:
(m+n-2)!/(m-1)!(n-1)!
但是需要注意的是,在题目给定的范围内进行阶乘计算的话会数据溢出,所以需要在计算分子的同时除以分母,从而避免数据溢出。感兴趣的朋友可以自己实现。

总结

这道题可以说是一道很经典的入门题目,既可以用搜索求解,又可以用动态规划求解,还可以用组合数学的思想直接求解,是一道入门的好题目。

你可能感兴趣的:(java,数据结构,动态规划,leetcode,算法)