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

一维前缀和与二维前缀和的详细用法和介绍

一、一维前缀和

  1. 定义
    • 对于数组(a),其前缀和数组(s)定义为(s[i]=a+a[1]+... +a[i]),主要用途是快速计算数组中任意区间的和。
  2. 用法
    • 初始化前缀和数组
      • 代码实现:
        int a[N];  // 原数组
        int s[N];  // 前缀和数组
        s[0]=a[0];
        for (int i = 1; i < N; i++) {
            s[i]=s[i - 1]+a[i];
        }
        
    • 查询区间和
      • 若查询区间([l,r])的和,可使用(s[r]-s[l - 1])。若(l == 0),则直接返回(s[r])。
      • 代码实现:
        int query(int l, int r) {
            if (l == 0) return s[r];
            return s[r]-s[l - 1];
        }
        
  3. 示例
    • 代码示例:
      #include <stdio.h>
      #define N 5
      int main() {
          int a[N]={1,2,3,4,5};
          int s[N];
          s[0]=a[0];
          for (int i = 1; i < N; i++) {
              s[i]=s[i - 1]+a[i];
          }
          printf("Sum from index 1 to 3: %d\n", query(1,3));  // 输出: 9
          return 0;
      }
      

二、二维前缀和

  1. 定义
    • 对于二维数组(a),其前缀和数组(s)定义为(s[i][j]=a[0][0]+..... +a[i][j]),主要用途是快速计算二维数组中任意子矩阵的和。
  2. 用法
    • 初始化前缀和数组
      • 代码实现:
        int a[N][M];  // 原二维数组
        int s[N][M];  // 前缀和数组
        s[0][0]=a[0][0];
        for (int i = 1; i < N; i++) {
            s[i][0]=s[i - 1][0]+a[i][0];
        }
        for (int j = 1; j < M; j++) {
            s[0][j]=s[0][j - 1]+a[0][j];
        }
        for (int i = 1; i < N; i++) {
            for (int j = 1; j < M; j++) {
                s[i][j]=s[i - 1][j]+s[i][j - 1]-s[i - 1][j - 1]+a[i][j];
            }
        }
        
    • 查询子矩阵和
      • 若查询子矩阵((x1,y1))到((x2,y2))的和,可使用(s[x2][y2]-s[x1 - 1][y2]-s[x2][y1 - 1]+s[x1 - 1][y1 - 1])。若(x1 == 0)或(y1 == 0),则需特殊处理。
      • 代码实现:
        int query(int x1, int y1, int x2, int y2) {
            if (x1 == 0 && y1 == 0) return s[x2][y2];
            if (x1 == 0) return s[x2][y2]-s[x2][y1 - 1];
            if (y1 == 0) return s[x2][y2]-s[x1 - 1][y2];
            return s[x2][y2]-s[x1 - 1][y2]-s[x2][y1 - 1]+s[x1 - 1][y1 - 1];
        }
        
  3. 示例
    • 代码示例:
      #include <stdio.h>
      #define N 3
      #define M 3
      int main() {
          int a[N][M] = {
              {1,2,3},
              {4,5,6},
              {7,8,9}
          };
          int s[N][M];
          s[0][0]=a[0][0];
          for (int i = 1; i < N; i++) {
              s[i][0]=s[i - 1][0]+a[i][0];
          }
          for (int j = 1; j < M; j++) {
              s[0][j]=s[0][j - 1]+a[0][j];
          }
          for (int i = 1; i < N; i++) {
              for (int j = 1; j < M; j++) {
                  s[i][j]=s[i - 1][j]+s[i][j - 1]-s[i - 1][j - 1]+a[i][j];
              }
          }
          printf("Sum from (1,1) to (2,2): %d\n", query(1,1,2,2));  // 输出: 28
          return 0;
      }
      

s[i][j]=s[i - 1][j]+s[i][j - 1]-s[i - 1][j - 1]+a[i][j];此代码可转化为子矩阵面积来理解

三、总结

  • 一维前缀和:用于快速计算数组中任意区间的和。
  • 二维前缀和:用于快速计算二维数组中任意子矩阵的和。
  • 这两种前缀和技巧在处理区间和问题时非常高效,能够将时间复杂度从(O(n))或(O(n^{2}))降低到(O(1))。

相关文章:

  • 局域网设备访问虚拟机 挂载NFS
  • 算法刷题记录——LeetCode篇(7) [第601~700题](持续更新)
  • dify创建第一个Agent
  • cmakelist中添加opencv
  • 【css酷炫效果】纯CSS实现科技感网格背景
  • 基于ros2与moveit2开发的yolo识别抓取虚拟机械臂
  • 开源模型:加速构建智能生态,引领人工智能新未来
  • Linux系统管理与编程07:任务驱动综合应用
  • 【鸿蒙开发】Hi3861学习笔记- UDP客户端
  • 第十六届蓝桥杯康复训练--6
  • C语言入门教程100讲(7)类型转换
  • 【算法学习计划】动态规划 -- 背包问题(01背包和完全背包)
  • git工作区、暂存区、本地仓库、远程仓库的区别和联系
  • 在Android Studio中,如何快速为变量添加m?
  • Vue3 0基础入门,三分钟掌握vue3核心知识
  • CentOS8 安装 Docker-CE
  • How to install samba on Linux mint 22.1
  • 字节跳动算法高频题:动态规划最优模板
  • C语言入门教程100讲(2)变量与常量
  • 计算机二级 web程序设计 知识点 考点大全
  • 最新研究:新型合成小分子可“精准杀伤”癌细胞
  • 福建宁德市长张永宁拟任设区市党委正职,曾获评全国优秀县委书记
  • 中铁房地产24.7亿元竞得上海松江新城宅地,溢价率20.42%
  • 陕西永寿4岁女童被蜜蜂蜇伤致死,当地镇政府介入处理
  • 观察|印巴交火开始升级,是否会升级为第四次印巴战争?
  • 金正恩视察重要军工企业要求推进武力强化变革