JavaScript 算法系列---動態規劃

很久之前接觸過這樣一道題目,總共有十層階梯,從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);
};

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章