JavaScript 算法系列---动态规划

被刻印的时光 ゝ 提交于 2019-12-24 12:27:18
很久之前接触过这样一道题目,总共有十层阶梯,从1层开始往上爬,每次可以上1层或者2层,问到10层总共有多少种方法?

思路:这个问题就是动态规划的一个经典例子,所谓动态规划,就是把复杂的问题进行拆解,拆解成一个个子问题,而这类问题最后非常适合使用递归来解决。诸如这道题目,可以记到某层阶梯的走法为F(n),那么到10层阶梯就是F(10)。 那么F(10)等于什么呢,这里进行假设,如果只差最后一次就可以走到10层,那么此时有几种情况呢?

  1. 在9层,往上走1步即可。
  2. 在8层,往上走2步即可。

那么此时可以得出F(10)=F(9)+F(8); — 最优子结构

其实这里就可以得出F(n)=F(n-1) + F(n-2) — 状态转移方程

而当n=2时,也就是走上2层,马上可以知道只有2种方法(0->2,0->1->2)
也就是F(2)=2,同理F(1)=1. — 边界情况

写成代码也很容易,这里就不写了。


然后这次还遇到了一个类似的题目,源自力扣
链接
其实大致的思路还是一样的,只是增加了对二维数组中,某一个数字的判断逻辑,刚刚开始我是这样做的

/**
 * @param {number[][]} obstacleGrid
 * @return {number}
 */
var uniquePathsWithObstacles = function(obstacleGrid) {
    // 坐标轴向下为x轴,向右为y轴
    // obstacleGrid的数组长度为n,表示矩阵高度
    // 其中每个元素的长度都是m,表示矩阵宽度

    var map = new Map();
    
    var F = function (x,y){
        // x,y 分别为网格的纵坐标.横坐标
        /* 0=<x<=n-1 */
        /* 0=<y<=m-1 */

        if (x ===0 && y === 0) {
            return obstacleGrid[x][y]==0 ? 1:0;
        }

         if (obstacleGrid[x][y] === 1){
            return 0;
        } else {
            if (x === 0) {
                return F(x,y-1);
            } else if (y === 0) {
                return F(x-1,y);
            } else {
                return F(x-1,y) + F(x,y-1);
            }
        }
    }

    return F(obstacleGrid.length - 1,obstacleGrid[0].length - 1);
};

但是某一个测试用例却显示超时了,所以这里得做一些额外的处理,我的思路是对某些计算的结果做一下缓存,每一次执行F(n)时先去Map里面取,如果取不到再进行递归运算,并缓存下来。改动后的代码如下

/**
 * @param {number[][]} obstacleGrid
 * @return {number}
 */


var uniquePathsWithObstacles = function(obstacleGrid) {
    // 坐标轴向下为x轴,向右为y轴
    // obstacleGrid的数组长度为n,表示矩阵高度
    // 其中每个元素的长度都是m,表示矩阵宽度

    var map = new Map();

    var cacheCalc = function (x,y) {
        if (map.has([x,y].join(','))) return map.get([x,y].join(','));
        else {
            var cacheValue = F(x,y);
            map.set([x,y].join(','),cacheValue);
            return cacheValue;
        }
    }

    var F = function (x,y){
        // x,y 分别为网格的纵坐标.横坐标
        /* 0=<x<=n-1 */
        /* 0=<y<=m-1 */

        if (x ===0 && y === 0) {
            return obstacleGrid[x][y]==0 ? 1:0;
        }

         if (obstacleGrid[x][y] === 1){
            return 0;
        } else {
            if (x === 0) {
                return cacheCalc(x,y-1);
            } else if (y === 0) {
                return cacheCalc(x-1,y);
            } else {
                return cacheCalc(x-1,y) + cacheCalc(x,y-1);
            }
        }
    }

    return F(obstacleGrid.length - 1,obstacleGrid[0].length - 1);
};

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!