zoukankan      html  css  js  c++  java
  • LeetCode 数组:62. 不同路径(动态规划 带记忆的递归)

    ,接下来

    在没有接触过动态规划之前,是这样思考这个题的。

    首先想到的就是递归中青蛙跳台阶的问题,自然想到递归。就使用原函数 int uniquePaths(int m, int n)

    • 函数的作用,遵循规则的情况下,有多少中途径到达坐标为(m-1,n-1)的位置
    • 递归终止条件:原点(m=n=1),函数返回1,如果m==0||n==0也是返回1(只有一种)
    • 递归关系:uniquePaths(m,n)=uniquePaths(m-1,n)+uniquePaths(m,n-1)

    代码完成如下:

    class Solution {
        public int uniquePaths(int m, int n) {
            if(m==1||n==1)
            {return 1;}
    
            return uniquePaths(m-1,n)+uniquePaths(m,n-1);
        }
    }

    然而超时了。。。

    递归有重复计算的问题,在很多格子中,明明曾经已经计算过结果,但是碰到仍然向后继续递归了:

    加一个数组,用于保存已经计算的结果

    class Solution {
        int[][] dp = new int[100][100];
        public int uniquePaths(int m, int n) {
            return cycle(m-1,n-1);
        }
        public int cycle(int i,int j){
            if(i == 0 || j == 0) return 1;
            if(dp[i][j] != 0) return dp[i][j];
            dp[i][j] = cycle(i-1,j)+cycle(i,j-1);
            return dp[i][j];
        }
    }

    通过接下来看动态规划的算法。

    动态规划是正着推,而且有一个用于存放结果的一维/二维数组,大部分问题是二维的。

    首先需要确认该问题是否符合动态规划解题要求
    动态规划适合解决的问题模型符合"一个模型三个特性"
    一个模型可以概括为:多阶段决策最优解模型; 本题目第一行是已经定好了都是1,
    在第二行的时候,每个方格的值都是该方格左边的格和该方格上边的格的总和,以此类推,满足.
    • 特性1:最优子结构;每个阶段的状态或值都是通过前面阶段的状态或值推导出来的,满足.
    • 特性2:无后效性;每个阶段的状态值一旦确定之后,是不受后面阶段状态值所影响的,满足.
    • 特性3:重复子问题;从递归解法中就能看出来有重复子问题的计算,满足.
     
    接下来,该分析如何套用动态规划解题步骤
    首先,定义二维数组保存路径条数,按照递归中分析得出第一行和第一列都是1,所以二维数组直接定义成如此
    然后分阶段阶段,每一横行的处理就是一个阶段,通过上一行就能推导出下一行的状态值
    在每一个阶段中,同一行中的方格,是其左边方格的值加上一行方格的总和
    最后返回二维数组最后一个元素的值即可.
    class Solution {
        public int uniquePaths(int m, int n) {
            int [][] dp = new int[m+1][n+1];
            //
            for(int i = 1;i<m+1;i++){
                //
                for(int j = 1;j<n+1;j++){
                    if(i == 1 && j == 1){
                        dp[1][1] = 1;
                    }else{
                        //状态转移方程
                        dp[i][j] = dp[i-1][j] + dp[i][j-1];
                    }
                }
            }
            return dp[m][n];
        }
    }

    这样的时间复杂度和空间复杂度都是om*n

    有优化的办法,把空间复杂度优化为O2n或者On

    优化一:将一个表优化成了表中我们需要的两行

    优化二:在优化一的基础上,将两行优化成了我们需要的当前行,因为cur未更新前保存的结果是上一行的结果

    另外,这道题其实直接排列组合就能做:

  • 相关阅读:
    Docker容器Centos容器安装openssh
    DEVOPS技术实践_15:使用Docker作为Jenkins的slave
    DEVOPS技术实践_14:使用docker部署jenkins
    oracle数据库创建实例
    Java 覆写初探
    Java super和this小结
    Java 继承学习
    Java 数据表映射
    Java 单向链表学习
    Java 继承初探
  • 原文地址:https://www.cnblogs.com/take-it-easy/p/13445490.html
Copyright © 2011-2022 走看看