DeepSeek LeetCode 3700. 锯齿形数组的总数 II JavaScript实现
核心思路
与 Rust/Java 版本一致,使用矩阵快速幂加速 DP。
· 状态向量长度 2m(m = r-l+1 ≤ 75)
· 转移矩阵 T:
newUp[i] = sum(down[0..i-1])
newDown[i] = sum(up[i+1..m-1])
· 初始向量全为 1
· 答案 = sum(T^(n-1) * v) % MOD
---
JavaScript 实现
```javascript
/**
* @param {number} n
* @param {number} l
* @param {number} r
* @return {number}
*/
var zigZagArrays = function(n, l, r) {
const MOD = 1000000007;
const m = r - l + 1;
const size = 2 * m;
// 构建转移矩阵 T (size x size)
const T = Array.from({ length: size }, () => Array(size).fill(0));
for (let i = 0; i < m; i++) {
// newUp[i] = sum(down[0..i-1])
for (let j = 0; j < i; j++) {
T[i][m + j] = 1;
}
// newDown[i] = sum(up[i+1..m-1])
for (let j = i + 1; j < m; j++) {
T[m + i][j] = 1;
}
}
// 初始向量 (长度为1时,up和down全为1)
const v = Array(size).fill(1);
// 矩阵快速幂:计算 T^(n-1) * v
const matMul = (A, B) => {
const n = A.length;
const C = Array.from({ length: n }, () => Array(n).fill(0));
for (let i = 0; i < n; i++) {
for (let k = 0; k < n; k++) {
if (A[i][k] === 0) continue;
const aik = A[i][k];
const rowB = B[k];
const rowC = C[i];
for (let j = 0; j < n; j++) {
rowC[j] = (rowC[j] + aik * rowB[j]) % MOD;
}
}
}
return C;
};
const matVecMul = (A, vec) => {
const n = A.length;
const res = Array(n).fill(0);
for (let i = 0; i < n; i++) {
let sum = 0;
const row = A[i];
for (let j = 0; j < n; j++) {
sum = (sum + row[j] * vec[j]) % MOD;
}
res[i] = sum;
}
return res;
};
// 快速幂
let exp = n - 1;
// 单位矩阵
let resultMat = Array.from({ length: size }, () => Array(size).fill(0));
for (let i = 0; i < size; i++) {
resultMat[i][i] = 1;
}
let base = T;
while (exp > 0) {
if (exp & 1) {
resultMat = matMul(resultMat, base);
}
base = matMul(base, base);
exp >>= 1;
}
const resultVec = matVecMul(resultMat, v);
let ans = 0;
for (let val of resultVec) {
ans = (ans + val) % MOD;
}
return ans;
};
```
---
更简洁版本(利用 BigInt 避免溢出)
由于 JS 中 Number 在乘法时可能溢出(MOD^2 ≈ 1e18,小于 Number.MAX_SAFE_INTEGER ≈ 9e15,实际会溢出),建议使用 BigInt 确保精度:
```javascript
var zigZagArrays = function(n, l, r) {
const MOD = 1000000007n;
const m = r - l + 1;
const size = 2 * m;
// 构建转移矩阵 (使用 BigInt)
const T = Array.from({ length: size }, () => Array(size).fill(0n));
for (let i = 0; i < m; i++) {
for (let j = 0; j < i; j++) T[i][m + j] = 1n;
for (let j = i + 1; j < m; j++) T[m + i][j] = 1n;
}
const v = Array(size).fill(1n);
const matMul = (A, B) => {
const n = A.length;
const C = Array.from({ length: n }, () => Array(n).fill(0n));
for (let i = 0; i < n; i++) {
for (let k = 0; k < n; k++) {
if (A[i][k] === 0n) continue;
const aik = A[i][k];
const rowB = B[k];
const rowC = C[i];
for (let j = 0; j < n; j++) {
rowC[j] = (rowC[j] + aik * rowB[j]) % MOD;
}
}
}
return C;
};
const matVecMul = (A, vec) => {
const n = A.length;
const res = Array(n).fill(0n);
for (let i = 0; i < n; i++) {
let sum = 0n;
const row = A[i];
for (let j = 0; j < n; j++) {
sum = (sum + row[j] * vec[j]) % MOD;
}
res[i] = sum;
}
return res;
};
let exp = n - 1;
let resultMat = Array.from({ length: size }, () => Array(size).fill(0n));
for (let i = 0; i < size; i++) resultMat[i][i] = 1n;
let base = T;
while (exp > 0) {
if (exp & 1) resultMat = matMul(resultMat, base);
base = matMul(base, base);
exp >>= 1;
}
const resultVec = matVecMul(resultMat, v);
let ans = 0n;
for (let val of resultVec) ans = (ans + val) % MOD;
return Number(ans);
};
```
---
复杂度
· 时间复杂度:O((2m)^3 \log n),m \le 75
· 空间复杂度:O(m^2)
示例
```javascript
console.log(zigZagArrays(3, 1, 3)); // 10
console.log(zigZagArrays(3, 4, 5)); // 2
```
更多推荐

所有评论(0)