当前位置: 首页 > news >正文

深入解析:动态规划的“升维”之技:二维前缀和,让矩阵查询“降维打击”

深入解析:动态规划的“升维”之技:二维前缀和,让矩阵查询“降维打击”

 哈喽,各位,我是前端L。

在 上一篇文章 中,我们刚刚掌握了一维世界里的“闪电查询”秘籍——前缀和。通过一次 O(n) 的预处理,我们实现了 O(1) 的区间和查询。这个“空间换时间”的策略是如此优雅和强大。

现在,是时候将我们的战场,从一条“线”扩展到一个“面”了!我们将把前缀和的思想,从一维升维到二维,构建一个能够实现矩阵区域和 O(1) 查询的“超级索引”。这不仅是技巧的升级,更是对“容斥原理”这一深刻数学思想的一次精彩演绎。

力扣 304. 二维区域和检索 - 矩阵不可变

https://leetcode.cn/problems/range-sum-query-2d-immutable/

题目分析: 你需要设计一个数据结构 NumMatrix

  • NumMatrix(vector<vector<int>>& matrix):用一个二维矩阵 matrix 初始化。

  • int sumRegion(int row1, int col1, int row2, int col2):返回该矩阵中,由 (row1, col1)(左上角)和 (row2, col2)(右下角)定义的矩形区域内所有元素的和。

核心约束:

  1. matrix不可变

  2. sumRegion 会被频繁调用

和一维情况一样,“频繁调用”就是最强的信号:预处理势在必行!

从一维到二维:前缀和的优雅“升维”

我们已经知道,一维前缀和 preSum[i] 代表 nums[0...i-1] 的和。现在,我们需要一个二维的 preSum 矩阵。

1. DP状态定义 (二维前缀和的核心):preSum[i][j] 表示:原矩阵 matrix 中,以 (0, 0) 为左上角,以 (i-1, j-1) 为右下角的那个矩形区域内所有元素的和。

2. 如何构建 preSum 矩阵?—— 容斥原理的第一次闪耀 这是二维前缀和最精妙的地方。如何递推计算 preSum[i][j]? 想象一下 preSum[i][j] 所代表的那个大矩形。我们可以通过它相邻的、更小的三个前缀和矩形来构建它。

       (j-1)   (j)(i-1) +-------+-----+|   A   |  B  |  <- preSum[i-1][j] = A+B+-------+-----+(i) |   C   |  D  |  <- matrix[i-1][j-1] = D+-------+-----+^|preSum[i][j-1] = A+C

我们想求 A+B+C+D

  • 我们可以先加上它上方的矩形 A+B (preSum[i-1][j])。

  • 再加上它左方的矩形 A+C (preSum[i][j-1])。

  • 这时,(A+B) + (A+C),我们发现左上角的区域 A (preSum[i-1][j-1]) 被重复加了两次!必须减掉一次。

  • 最后,别忘了加上当前右下角那个单独的元素 D (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]

3. 如何使用 preSum 矩阵查询?—— 容斥原理的第二次闪耀 现在,我们要查询以 (r1, c1) 为左上角,(r2, c2) 为右下角的矩形和(我们称之为区域 D)。

      (c1)    (c2+1)
(r1) +-------+-------+|   A   |   B   |+-------+-------+
(r2+1)|   C   |   D   |+-------+-------+
  • 我们可以先获取覆盖 A+B+C+D 的最大前缀和矩形:preSum[r2+1][c2+1]

  • 然后,减去我们不想要的上方矩形 A+BpreSum[r1][c2+1]

  • 再减去我们不想要的左方矩形 A+CpreSum[r2+1][c1]

  • 这时,(A+B+C+D) - (A+B) - (A+C),我们发现左上角的区域 A (preSum[r1][c1]) 被重复减了两次!必须加回来一次。

于是,我们得到了二维区域和查询的 O(1) 公式: sumRegion = preSum[r2+1][c2+1] - preSum[r1][c2+1] - preSum[r2+1][c1] + preSum[r1][c1]

代码实现

class NumMatrix {
private:// preSum[i][j] 存储 matrix[0...i-1][0...j-1] 的和vector> preSum; // 使用long long防止溢出
public:NumMatrix(vector>& matrix) {if (matrix.empty() || matrix[0].empty()) {return;}int m = matrix.size();int n = matrix[0].size();// 初始化 preSum 矩阵,大小 (m+1)x(n+1)preSum.resize(m + 1, vector(n + 1, 0));// --- O(m*n) 预处理 ---for (int i = 1; i <= m; ++i) {for (int 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];}}}int sumRegion(int row1, int col1, int row2, int col2) {// --- O(1) 查询 ---return preSum[row2 + 1][col2 + 1]- preSum[row1][col2 + 1]- preSum[row2 + 1][col1]+ preSum[row1][col1];}
};
/*** Your NumMatrix object will be instantiated and called as such:* NumMatrix* obj = new NumMatrix(matrix);* int param_1 = obj->sumRegion(row1,col1,row2,col2);*/

总结:二维前缀和——预处理的“杀手锏”

今天,我们成功地将一维前缀和的智慧,“升维”到了二维世界。二维前缀和技术,是处理静态二维矩阵区间查询问题的“标准答案”和“杀手锏”。

其核心,在于两次巧妙运用容斥原理 (Inclusion-Exclusion Principle)

  1. 构建时当前 = 上 + 左 - 左上 + 自己

  2. 查询时目标 = 右下 - 上 - 左 + 左上

掌握了二维前缀和,你就拥有了在二维平面上进行 O(1) 区域求和的“超能力”。这不仅在算法竞赛中极其有用,在实际的图像处理、数据分析等工程领域,也同样是构建高效系统的基石。

咱们下期见!

http://www.jsqmd.com/news/327373/

相关文章:

  • [嵌入式系统-180]:PLC运动控制 VS 运动控制卡
  • 彼得林奇如何看待公司的市场定位
  • 2025年智能问答系统演进:从关键词匹配到语义理解的跨越 - 教程
  • 学习1
  • AI应用架构师实战:数据资产评估智能体的Serverless部署,降本增效价值提升
  • 【有源码】基于Python的睡眠压力监测分析系统-基于Spark数据挖掘的睡眠压力动态可视化分析平台
  • 电商修图新解法:AI批量换背景,告别熬夜实现高效批量出片
  • 关于
  • 智能决策支持AI平台接口文档设计:架构师如何让上下游快速对接决策服务?
  • 我们来说说 Redis 中 Zset 的底层实现
  • 压力测试实战:基于Locust的高并发场景稳定性验证
  • dify 教程目录
  • 必看!2026年单北斗GNSS水库变形监测TOP五大推荐产品
  • 精选的优秀法证分析工具和资源列表
  • Astral3D 教程目录
  • Clipper2 教程目录
  • Docker 到底变成了什么?从“容器之王”到“开发者工具箱+AI 基建+安全公司”的奇妙漂流
  • Clipper1 教程目录
  • 金融科技创新对传统金融业的冲击与机遇
  • 独家分享:一线提示工程架构师用Agentic AI解决金融客户留存问题的实战技巧
  • Maven 引入外部依赖
  • Java毕设项目:基于Java Web的毕业设计选题管理系统的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 使用 JTS 快速检测狭窄多边形
  • 【毕业设计】基于Java Web的毕业设计选题管理系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • PDF一机一码加密大师1.1.0更新至2026最新版, 强力加密PDF, 无需额外安装阅读器, 附CSDN下载地址
  • 链表 part02
  • [豪の算法奇妙冒险] 代码随想录算法训练营第三十七天 | 完全背包理论基础、518-零钱兑换Ⅱ、377-组合总和Ⅳ
  • AppML 案例未来
  • Python 循环嵌套
  • 期末考小记