构建前缀和
构建「前缀和」(Prefix Sum)是一种非常常用的算法技巧,用于在 常数时间内查询子区间的和,适用于数组、二维矩阵等结构。
📌 一维前缀和
✅ 定义:
给定一个数组 nums
,前缀和数组 preSum
的定义是:
preSum[i] = nums[0] + nums[1] + ... + nums[i - 1]
也就是:
preSum[0] = 0
preSum[i] = preSum[i - 1] + nums[i - 1]
然后,对于任意区间 [l, r]
(闭区间),其和为:
sum = preSum[r + 1] - preSum[l]
📘 示例(JavaScript):
// 构建前缀和数组 function buildPrefixSum(nums) { const preSum = [0]; for (let i = 0; i < nums.length; i++) { preSum.push(preSum[i] + nums[i]); } return preSum; } // 查询区间和 [l, r] function rangeSum(preSum, l, r) { return preSum[r + 1] - preSum[l]; } // 示例 const nums = [2, 4, 5, 7, 1]; const preSum = buildPrefixSum(nums); console.log(rangeSum(preSum, 1, 3)); // 输出:4+5+7 = 16
📌 二维前缀和(矩阵)
✅ 定义:
给定一个二维数组 matrix
,前缀和数组 preSum
满足:
preSum[i][j] = matrix[0][0] + matrix[0][1] + ... + matrix[i-1][j-1]
即:
preSum[i][j] = preSum[i-1][j] + preSum[i][j-1] - preSum[i-1][j-1] + matrix[i-1][j-1]
然后查询任意子矩形 (x1, y1) ~ (x2, y2)
的和为:
sum = preSum[x2+1][y2+1] - preSum[x1][y2+1] - preSum[x2+1][y1] + preSum[x1][y1]
📘 示例(JavaScript):
// 构建二维前缀和 function build2DPrefixSum(matrix) { const m = matrix.length, n = matrix[0].length; const preSum = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; i++) { for (let j = 1; j <= n; j++) { preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] - preSum[i - 1][j - 1] + matrix[i - 1][j - 1]; } } return preSum; } // 查询矩形和:左上(x1, y1),右下(x2, y2) function range2DSum(preSum, x1, y1, x2, y2) { return ( preSum[x2 + 1][y2 + 1] - preSum[x1][y2 + 1] - preSum[x2 + 1][y1] + preSum[x1][y1] ); } // 示例 const matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; const preSum = build2DPrefixSum(matrix); console.log(range2DSum(preSum, 0, 0, 1, 1)); // 输出:1+2+4+5 = 12
🔍 应用场景
类型 | 使用场景 |
---|---|
一维前缀和 | 连续子数组和、子数组和为 K 的问题 |
二维前缀和 | 子矩阵求和 |
前缀和 + 差分数组 | 区间更新 + 区间查询 |
评论(0)
暂无评论