【算法】一维前缀和以及二维前缀和

一维前缀和

适用场景

  • 求一段区间的和

比如有一个数列 :
在这里插入图片描述
如果我们要求 [l,r]即某个区间内的数组和的时候,思路就是每遍历一个元素就进行求和,记录下加到al时的和值以及加到ar时的和值,两个值相减就得到区间和了。

这时求一次和的情况,时间复杂度是O(n),那如果要进行多次区间求和,每次都要进行一次这样的操作,那么n次的时间复杂度就是O(n * n)。

为了避免出现上面的情况,我们以空间换时间,在每次进行求和的时候将和值记录下来,也就是说我们会另外构造一个数组,这个数组就是前缀和数组。这样我们只需遍历一次数组,在需要求区间和的时候直接从前缀和数组中取出相应的值进行减法就可以了。

示例

在这里插入图片描述
java参考代码:

package org.example;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); //序列长度
        int m = sc.nextInt(); //询问次数
        int[] nums = new int[n]; //序列数组
        int[] sums = new int[n]; //前缀和数组
        //构造序列数组的同时构造前缀和数组
        for (int i = 0; i < n; i++) {
            nums[i] = sc.nextInt();
            //构造前缀和数组
            if (i == 0) {
                sums[i] = nums[i];
            } else {
                sums[i] = sums[i - 1] + nums[i];
            }
        }
        while ( m-- > 0) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            System.out.println("区间和:" + (sums[r] - sums[l]));
        }
    }
}

二维前缀和

适用场景

  • 求一个矩阵中任意子矩阵的数之和

一种情况

如果要求一个i*j(i行j列)的子矩阵的数之和,如图:
在这里插入图片描述

  1. 先求i * (j - 1)子矩阵的数之和,如图:
    在这里插入图片描述
  2. 再求(i - 1) * j 子矩阵的数之和,如图:
    在这里插入图片描述
  3. 将以上两值相加后再加上第i行第j列那个元素
  4. 最后一步去重,如图,灰色区域在前面两步加了两次,所以减去,重复的部分是(i - 1) * (j - 1)子矩阵
    在这里插入图片描述
    最后的公式就是:
    在这里插入图片描述

另一种情况

我们要求的子矩阵是中间的,如下图,我们要求黄色框子矩阵的数之和:
和前面的思路差不多。上面是要去重,下面这种情况则需要加上重复删除的部分。
在这里插入图片描述

示例

在这里插入图片描述
在这里插入图片描述
java参考代码:

package org.example;

import javax.sound.midi.Soundbank;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); //n行
        int m = sc.nextInt(); //m列
        int q = sc.nextInt(); //询问q次
        int[][] a = new int[n + 1][m + 1];  //构造矩阵
        int[][] s = new int[n + 1][m + 1];  //构造二维前缀和
        //构造矩阵和二维前缀和
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                a[i][j] = sc.nextInt();
                s[i][j] = s[i - 1][j] + s[i][j - 1] + a[i][j] - s[i - 1][j - 1];
            }
        }
        while (q-- > 0) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();
            System.out.println("子矩阵和:" + (s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]));
        }
    }
}

在这里插入图片描述

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-12 08:42:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-12 08:42:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-12 08:42:02       82 阅读
  4. Python语言-面向对象

    2024-03-12 08:42:02       91 阅读

热门阅读

  1. LeetCode题练习与总结:最长有效括号

    2024-03-12 08:42:02       46 阅读
  2. Linux系统架构----Nginx的服务优化

    2024-03-12 08:42:02       48 阅读
  3. 单例模式的几种实现方式

    2024-03-12 08:42:02       49 阅读
  4. C语言学习笔记day2

    2024-03-12 08:42:02       40 阅读
  5. 并发中的锁

    2024-03-12 08:42:02       42 阅读
  6. (C语言)球球大作战

    2024-03-12 08:42:02       36 阅读
  7. R 语言patchwork包拼图间隙

    2024-03-12 08:42:02       43 阅读
  8. 华为机考:HJ2 计算某字符出现次数

    2024-03-12 08:42:02       46 阅读
  9. MFC中字符串string类型和CString类型互转方法

    2024-03-12 08:42:02       38 阅读
  10. AI大语言模型GPT & R 生态环境领域数据统计分析

    2024-03-12 08:42:02       42 阅读
  11. 单调栈的用法

    2024-03-12 08:42:02       46 阅读
  12. 初级爬虫实战——巴黎圣母院新闻

    2024-03-12 08:42:02       41 阅读
  13. 手写redis机制

    2024-03-12 08:42:02       42 阅读
  14. Spring Data访问 MongoDB(十六)----CDI集成

    2024-03-12 08:42:02       41 阅读