零基础学算法100天第5天——二维前缀和(基础算法)(下)

简介: 零基础学算法100天第5天——二维前缀和(基础算法)

🎃 4.前缀和数组的使用


知道预处理的原理,那么使用起来就非常简单啦。还是根据图解帮助大家快速理解。


image.png

                                                 

image.png

     

image.png

       我们从这几个图来分析,蓝色矩阵是我们的目标求和矩阵,我们并无法直接通过二维数组求出来,我们设蓝色矩阵左上角的坐标为x1,y1以及右下角坐标为x2,y2。 我们可以先通过红色矩阵然后减去两个绿色的矩阵,其中黄色矩阵被减去了两次,所以我们还需要再加回来一次。


       所以已知两点坐标求该矩阵和的公式为:

image.png


      这个公式再次体现了为什么下标都要从1开始的好处,防止越界问题。          


🍋5.二维前缀和模板题练习


       1)、二维区域和检索


image.png


题目链接:二维区域和检索 - 矩阵不可变https://leetcode.cn/problems/range-sum-query-2d-immutable/


        和一维前缀和那题是一模一样的,只不过变成了二维状态,直接预处理出二维前缀和数组,再利用公式即可,要注意我们接收的数组下标是从0开始的。


       代码转换:


class NumMatrix {
    int[][] arr;
    public NumMatrix(int[][] matrix) {
        int n=matrix.length;
        if(n>0){
        int m=matrix[0].length;     
        arr=new int[n+1][m+1];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                arr[i+1][j+1]=arr[i][j+1]+arr[i+1][j]-arr[i][j]+matrix[i][j];
            }
        }
    }
}
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return  arr[row2+1][col2+1]-arr[row1][col2+1]-arr[row2+1][col1]+arr[row1][col1];
    }
}

2)、统计子矩阵


给定一个 N × M 的矩阵 A,请你统计有多少个子矩阵 (最小 1 × 1,最大 N × M) 满足子矩阵中所有数的和不超过给定的整数 K?      


题目链接:蓝桥杯2022年第十三届省赛真题-统计子矩阵 - C语言网https://www.dotcpp.com/oj/problem2659.html


          这道题是今年B++组中间的一道题目,几乎就是纯裸的二维前缀和题目,只不过如果不能拿满分,但还是能拿大部分的分,而且直接套模板就行,根本不需要怎么变形,这种分数的性价比更高。


image.png


        直接对原数组进行前缀和数组预处理,然后枚举左上角的坐标和右下角的坐标计算即可。


       代码转换:


import java.util.Scanner;
public class Main {
    static int N=510;
    static int[][] a=new int[N][N];
    static int[][] s=new int[N][N];
    static int res=0;
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        int k=sc.nextInt();
        for (int i = 1; i <=n; i++) {
            for (int j = 1; j <=m; j++) {
                a[i][j]=sc.nextInt();
            }
        }
        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];
            }
        }
        //枚举左上角坐标
        for (int i = 1; i <=n; i++) {
            for (int j = 1; j <=m; j++) {
                //枚举右下标
                for (int l = i; l <=n; l++) {
                    for (int o = j; o <=m; o++) {
                        if (check(i,j,l,o,k)) res++;
                        else break;
                    }
                }
            }
        }
        System.out.println(res);
    }
    //判断该矩阵和是否小于k
    static boolean check(int x1,int y1,int x2,int y2,int k){
        int h=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
        return h<=k;
    }
}


相关文章
|
3月前
|
算法
【算法】前缀和——二维前缀和模板题
【算法】前缀和——二维前缀和模板题
|
3月前
|
算法
【算法】前缀和——前缀和
【算法】前缀和——前缀和
|
2月前
|
存储 算法 Java
前缀和算法
本文介绍了前缀和及其变种在解决区间求和问题中的应用。首先,一维前缀和可通过预处理数组快速求得任意区间的和。接着,二维前缀和扩展了这一思想,适用于矩阵操作。此外,文章探讨了如何利用前缀和解决诸如“寻找数组中心下标”、“除自身以外数组的乘积”等问题,并进一步讲解了涉及哈希表优化的“和为 K 的子数组”等相关题目。最后,通过实例展示了如何在矩阵中高效计算特定区域的元素之和。文中包含代码示例与图解说明,便于理解。
43 0
前缀和算法
|
1月前
|
人工智能 算法 C++
一篇带你速通前缀和算法(C/C++)
一篇带你速通前缀和算法(C/C++)
|
4月前
|
人工智能 算法 JavaScript
【算法】前缀和与差分
算法学习——前缀和与差分(含一维和二维)
54 4
【算法】前缀和与差分
|
3月前
|
算法 C++
【算法】前缀和算法——和可被K整除的子数组
【算法】前缀和算法——和可被K整除的子数组
|
3月前
|
算法
【算法】前缀和算法——和为k的子数组之和
【算法】前缀和算法——和为k的子数组之和
|
3月前
|
算法
【算法】前缀和——除自身以外数组的乘积
【算法】前缀和——除自身以外数组的乘积
|
3月前
|
算法
【算法】前缀和——寻找数组的中心下标
【算法】前缀和——寻找数组的中心下标
|
5月前
|
机器学习/深度学习 算法
简单遗传算法 + 最低水平线算法求解二维排样问题
简单遗传算法 + 最低水平线算法求解二维排样问题
84 0
下一篇
无影云桌面