前缀和矩阵

前缀和矩阵(Prefix Sum Matrix)是一种预处理技术,用于快速计算二维矩阵中任意子矩阵的元素和。其核心思想是通过提前计算并存储每个位置左上角所有元素的和,将子矩阵和的查询时间从暴力计算的 (O(mn)) 优化到 (O(1))。以下是构建前缀和矩阵的详细步骤和示例:


文章目录

      • [1. 定义原矩阵与前缀和矩阵](#1. 定义原矩阵与前缀和矩阵)
      • [2. 构建前缀和矩阵的步骤](#2. 构建前缀和矩阵的步骤)
        • [步骤 1:初始化前缀和矩阵](#步骤 1:初始化前缀和矩阵)
        • [步骤 2:递推公式](#步骤 2:递推公式)
      • [3. 构建示例](#3. 构建示例)
      • [4. 查询子矩阵和](#4. 查询子矩阵和)
      • [5. 代码实现(C++)](#5. 代码实现(C++))
      • 关键点总结

1. 定义原矩阵与前缀和矩阵

  • 原矩阵 :一个 m X n 的二维数组 matrix,元素为整数或浮点数。
  • 前缀和矩阵 :一个与 matrix 同尺寸的二维数组 prefix,其中 prefix[i][j] 表示从左上角 (0,0) 到 (i,j) 形成的子矩阵所有元素之和。

2. 构建前缀和矩阵的步骤

步骤 1:初始化前缀和矩阵
  • 创建一个与原矩阵大小相同的二维数组 prefix。
  • 通常将 prefix 的索引从 (0,0) 开始(与 matrix 对齐)。
步骤 2:递推公式
  • 边界条件:

    • 当 i=0 且 j=0 时:

      markdown 复制代码
      							prefix[0][0] = matrix[0][0]
    • 当 i=0 时(第一行):

      markdown 复制代码
      					prefix[0][j] = prefix[0][j-1] + matrix[0][j]
    • 当 j=0 时(第一列):

      markdown 复制代码
      					prefix[i][0] = prefix[i-1][0] + matrix[i][0]
  • 一般情况 (i>0 且 j>0):

    markdown 复制代码
    				prefix[i][j] = matrix[i][j] + prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1]

    解释 :

    当前元素的值 matrix[i][j],加上上方子矩阵的和 prefix[i-1][j],加上左方子矩阵的和 prefix[i][j-1],再减去重复计算的左上角子矩阵 prefix[i-1][j-1]。


3. 构建示例

假设原矩阵 matrix 如下:

markdown 复制代码
                                           [1  2  3]
                                           [4  5  6]
                                           [7  8  9]

逐行构建前缀和矩阵 prefix:

  1. 初始化 prefix[0][0]:

    markdown 复制代码
    							prefix[0][0] = matrix[0][0] = 1
  2. 第一行(i=0):

    markdown 复制代码
    					prefix[0][1] &= prefix[0][0] + matrix[0][1] = 1 + 2 = 3 
                        prefix[0][2] &= prefix[0][1] + matrix[0][2] = 3 + 3 = 6 
  3. 第一列(j=0):

    markdown 复制代码
    					prefix[1][0] &= prefix[0][0] + matrix[1][0] = 1 + 4 = 5 
                        prefix[2][0] &= prefix[1][0] + matrix[2][0] = 5 + 7 = 12 
  4. 一般位置(i>0 且 j>0):

    • prefix[1][1]:

      markdown 复制代码
      								5 + 5 + 3 - 1 = 12
    • prefix[1][2]:

      markdown 复制代码
      								6 + 12 + 6 - 3 = 21
    • prefix[2][1]:

      markdown 复制代码
      								8 + 12 + 12 - 5 = 27
    • prefix[2][2]:

      markdown 复制代码
      								9 + 27 + 21 - 12 = 45

最终前缀和矩阵:

markdown 复制代码
                                            [1  3   6 ]
                                            [5  12  21]
                                            [12 27  45]

4. 查询子矩阵和

构建前缀和矩阵后,计算子矩阵 (x1, y1) 到 (x2, y2) 的和公式为:

markdown 复制代码
	Sum = prefix[x2][y2] - prefix[x1-1][y2] - prefix[x2][y1-1] + prefix[x1-1][y1-1]

示例 :

计算子矩阵 (1,1) 到 (2,2)(即原矩阵中的 5,6,8,9)的和:

markdown 复制代码
	Sum = 45 - 6 - 12 + 1 = 28

5. 代码实现(C++)

cpp 复制代码
#include <vector>
using namespace std;

vector<vector<int>> buildPrefixSum(vector<vector<int>>& matrix) {
    int m = matrix.size(), n = matrix[0].size();
    vector<vector<int>> prefix(m, vector<int>(n, 0));

    // 初始化第一行和第一列
    prefix[0][0] = matrix[0][0];
    for (int j = 1; j < n; j++) 
        prefix[0][j] = prefix[0][j-1] + matrix[0][j];
    for (int i = 1; i < m; i++) 
        prefix[i][0] = prefix[i-1][0] + matrix[i][0];

    // 填充其他位置
    for (int i = 1; i < m; i++) {
        for (int j = 1; j < n; j++) {
            prefix[i][j] = matrix[i][j] 
                          + prefix[i-1][j] 
                          + prefix[i][j-1] 
                          - prefix[i-1][j-1];
        }
    }
    return prefix;
}

关键点总结

  • 时间复杂度:构建前缀和矩阵需 (O(mn)),查询子矩阵和仅需 (O(1))。
  • 适用场景:频繁查询子矩阵和的场景(如动态规划、图像处理)。
  • 边界处理 :注意索引从 0 开始,避免越界访问。
相关推荐
CHPCWWHSU3 小时前
FreeCAD 源码解读:从 Property 到 Command,看一套 CAD 内核的完整闭环
c++·cad
代钦塔拉3 小时前
【C++/Qt 进阶】设计模式系列(5):适配器模式——给“不兼容的接口“贴一层翻译膜
c++·qt·设计模式
Mister Leon3 小时前
Nvidia Orin AGX实战之从量化到蒸馏:在 Orin 上落地的大模型压缩实战
人工智能·算法·机器学习
aqiu1111113 小时前
蓝桥杯真题复盘:Fibonacci 数列与黄金分割(C++ 算法详解)
c++·算法·蓝桥杯
phoenix@Capricornus3 小时前
LDA 协方差矩阵(MATLAB `fitcdiscr`)
算法·matlab·矩阵
lojox3 小时前
C++ 手写 STL list(双向循环链表)原理剖析与实现
c++·链表·list
青少儿编程课堂3 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会C/C++考级:拓扑排序课程表排课解析
c++·python·算法·bfs·信息学竞赛
暖焰核心3 小时前
二叉搜索树——从插入查到key-value改写
c++
草莓熊Lotso7 小时前
【C++ 基于微服务的即时通讯系统】etcd + brpc 从安装到服务注册发现全链路实战
网络·数据库·c++·redis·微服务·etcd
HPtiger13 小时前
数据结构——选择排序
数据结构·算法·排序算法