算法—动态规划(4)

232 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

今天介绍一下 tabulation 方法,主要需要几个步骤,在这里先总结一下

  • 把问题可视化
  • 确定可视化的表格大小,通常都是数组或者列表增加一个维度
  • 然后给出默认值
  • 定义一个 seed 初始值,也就是初始情况
  • 然后就开始迭代,迭代就是用当前值更新后来值来完成填表

上面写的有点 confusing,我们通过下面对斐波那契数列问题来展开对号入座地解释,首先我们可视化 就是画一个一维表格,我们这里求解 fib(6) 这里 n 为 6 那么列表大小就是 n + 1。然后给出默认值就是 0 ,然后定义一个 seed 值也就是初始条件或者 base case 值。所以这里给 table[1]=1table[1] = 1 然后我们设定 3 个指针,用当前值增加到随后两个位置的数,通过迭代移动指针来将当前值更新(加到)后面值。

010.png

const fib = (n) => {
    // 创建一个可视化数组 n+1 
    // 并且给出默认值 0
    const table = Array(n+1).fill(0);
    // 初始化 seed 
    table[1] = 1;
    // 迭代用当前值根据规则更新其他位置来填表
    for(let i = 0; i <= n; i++){
        table[i + 1] += table[i];
        table[i + 2] += table[i];
    }

    return table[n]
}

console.log(fib(6))

012.png

这个表格问题我们也可以 tabulation 方式来解决,这里 3×33 \times 3 大小网格从左上角出发到右下角的路径的数目,每次只可以向下或者向右移动一个格子。首先初始化一个 2 维表格,然后将其表格行和列增加一个行和一列为 4×44 \times 4 然后初始化默认值为 0,然后添加 seed 也就是一个 (1,1) 一个就只有一个路径也就是table[1][1]=1table[1][1] = 1 然后就开始迭代,每次移动指针,从左上角开始逐行移动,移动过程中基于当前值更新其右侧和下侧值,也就是将当前值追加到这两个单元格的值。知道移动右下角完成迭代过程。

const gridTraveler = (m,n)=>{
    const table = Array(m+1)
        .fill()
        .map(()=>Array(n+1).fill(0));
    // console.log(table)
    table[1][1] = 1
    // console.log(table)
    for (let i = 0; i <= m; i++) {
        for (let j = 0; j <= n; j++) {
            const current = table[i][j];
            if(j+1 <= n) table[i][j+1] += current;
            if(i+1 <= m) table[i+1][j] += current;
        }
    }

    return table[m][n]
}


console.log(gridTraveler(3,3))