在 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));
注意事项
-
避免引用问题:使用
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)); -
性能考虑:对于非常大的数组,初始化方式会影响性能
-
边界处理:动态规划中经常需要处理边界条件,创建数组时通常会让数组大小比问题规模大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];
}