在 JavaScript 中创建一维或二维数组用于动态规划题目

51 阅读2分钟

在 JavaScript 中创建数组用于动态规划题目

动态规划(DP)问题通常需要使用数组来存储中间结果,下面介绍在 JavaScript 中创建一维和二维数组的方法。

一维数组创建

1. 创建固定长度的一维数组

// 方法1: Array构造函数
const dp1 = new Array(5); // 创建长度为5的数组,元素为undefined

// 方法2: 字面量方式
const dp2 = []; // 创建空数组,之后可以动态添加

// 方法3: 创建并初始化
const dp3 = new Array(5).fill(0); // 创建长度为5的数组,并用0填充
const dp4 = Array.from({length: 5}, () => 0); // 同上,更灵活

2. 动态规划中常用的一维数组初始化

// 斐波那契数列初始化
const fib = new Array(n + 1).fill(0);
fib[1] = 1;
fib[2] = 1;

二维数组创建

1. 创建固定大小的二维数组

// 方法1: 使用fill和map
const rows = 3, cols = 4;
const dp1 = new Array(rows).fill(0).map(() => new Array(cols).fill(0));

// 方法2: 使用Array.from
const dp2 = Array.from({length: rows}, () => new Array(cols).fill(0));

// 方法3: 双重循环初始化
const dp3 = [];
for (let i = 0; i < rows; i++) {
    dp3[i] = new Array(cols).fill(0);
}

2. 动态规划中常用的二维数组初始化

// 背包问题初始化
const n = items.length; // 物品数量
const w = capacity; // 背包容量
const dp = new Array(n + 1).fill(0).map(() => new Array(w + 1).fill(0));

// 最长公共子序列初始化
const m = str1.length, n = str2.length;
const dp = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));

注意事项

  1. 避免引用问题:使用 fill 填充对象或数组时要注意是浅拷贝

    // 错误方式 - 所有行都引用同一个数组
    const wrong = new Array(3).fill(new Array(3).fill(0));
    
    // 正确方式
    const correct = new Array(3).fill(0).map(() => new Array(3).fill(0));
    
  2. 性能考虑:对于非常大的数组,初始化方式会影响性能

  3. 边界处理:动态规划中经常需要处理边界条件,创建数组时通常会让数组大小比问题规模大1

实际DP例子

斐波那契数列(一维数组)

function fib(n) {
    if (n <= 1) return n;
    const dp = new Array(n + 1).fill(0);
    dp[1] = 1;
    for (let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
}

最小路径和(二维数组)

function minPathSum(grid) {
    const m = grid.length, n = grid[0].length;
    const dp = new Array(m).fill(0).map(() => new Array(n).fill(0));
    
    dp[0][0] = grid[0][0];
    
    // 初始化第一行和第一列
    for (let i = 1; i < m; i++) dp[i][0] = dp[i-1][0] + grid[i][0];
    for (let j = 1; j < n; j++) dp[0][j] = dp[0][j-1] + grid[0][j];
    
    for (let i = 1; i < m; i++) {
        for (let j = 1; j < n; j++) {
            dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1]) + grid[i][j];
        }
    }
    
    return dp[m-1][n-1];
}