想要精通算法和SQL的成长之路 - 前缀和的应用

想要精通算法和SQL的成长之路 - 前缀和的应用

  • 前言
  • [一. 区域和检索 - 数组不可变](#一. 区域和检索 - 数组不可变)
  • [二. 二维区域和检索 - 矩阵不可变](#二. 二维区域和检索 - 矩阵不可变)
    • [2.1 前缀和的计算](#2.1 前缀和的计算)
    • [2.2 用前缀和计算二维区域和](#2.2 用前缀和计算二维区域和)
  • [三. 矩形区域不超过 K 的最大数值和](#三. 矩形区域不超过 K 的最大数值和)

前言

想要精通算法和SQL的成长之路 - 系列导航

一. 区域和检索 - 数组不可变

原题链接

思路如下:

  1. 我们统计每个元素的前缀和为preSum(i) ,不包括num[i]的值。
  2. 那么对于索引[left, right]之间的和,就可以利用前缀和来计算,值为:preSum(right+1) - preSum(left)

代码如下:

java 复制代码
public class NumArray {
    int[] preSums;

    public NumArray(int[] nums) {
        int n = nums.length;
        // 计算前缀和,指 preSums[i] 在下标i之前的元素和
        preSums = new int[n + 1];
        for (int i = 0; i < n; i++) {
            preSums[i + 1] = preSums[i] + nums[i];
        }
    }

    public int sumRange(int left, int right) {
        return preSums[right + 1] - preSums[left];
    }
}

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

原题链接

2.1 前缀和的计算

我们先来看下,对于任意一个元素,从下标 (0,0)(i,j) 之间的区域和怎么计算。如图:

换成代码就是:

java 复制代码
preSums[i][j] = preSums[i][j - 1] + preSums[i - 1][j] - preSums[i - 1][j - 1] + matrix[i-1][j-1];

2.2 用前缀和计算二维区域和

如图:我们想计算A到D之间的区域和:

代码如下:(在设置二维数组的时候,可以增加一行和一列作为虚拟节点,数值为0)

java 复制代码
preSums[row2+1][col2+1] - preSums[row2+1][col1] - preSums[row1][col2+1] + preSums[row1][col1];

完整代码如下:

java 复制代码
public class NumMatrix {
    int preSums[][];

    public NumMatrix(int[][] matrix) {
        int row = matrix.length + 1;
        int col = matrix[0].length + 1;
        preSums = new int[row][col];
        // 第一列第一行的数值都是0
        for (int i = 1; i < row; i++) {
            for (int j = 1; j < col; j++) {
                preSums[i][j] = preSums[i][j - 1] + preSums[i - 1][j] - preSums[i - 1][j - 1] + matrix[i-1][j-1];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return preSums[row2+1][col2+1] - preSums[row2+1][col1] - preSums[row1][col2+1] + preSums[row1][col1];
    }
}

三. 矩形区域不超过 K 的最大数值和

原题链接

这题目可以在题目二的基础上,我们自行遍历,以开始节点(startRow,startCol) 为起始位置,在遍历所有情况的结束节点(endRow,endCol) 之间的区域和。满足条件:

  • startRow <= endRow < row
  • startCol <= endCol < col

由于是二维空间,两个节点,因此一共是4层循环:

java 复制代码
public class Test363 {
    int preSum[][];

    public int maxSumSubmatrix(int[][] matrix, int k) {
        int row = matrix.length + 1;
        int col = matrix[0].length + 1;
        preSum = new int[row][col];
        // 结算前缀和
        for (int i = 1; i < row; i++) {
            for (int j = 1; j < col; j++) {
                preSum[i][j] = preSum[i][j - 1] + preSum[i - 1][j] - preSum[i - 1][j - 1] + matrix[i - 1][j - 1];
            }
        }
        int max = Integer.MIN_VALUE;
        // 起始节点的横纵坐标
        for (int startRow = 1; startRow < row; startRow++) {
            for (int startCol = 1; startCol < col; startCol++) {
            	// 结束节点的横纵坐标
                for (int endRow = startRow; endRow < row; endRow++) {
                    for (int endCol = startCol; endCol < col; endCol++) {
                        // 求得两个节点之间的区域和
                        int sumRegion = sumRegion(startRow, startCol, endRow, endCol);
                        if (sumRegion <= k) {
                            max = Math.max(max, sumRegion);
                        }
                    }
                }
            }
        }
        return max;
    }

    public int sumRegion(int row1, int col1, int row2, int col2) {
        return preSum[row2][col2] - preSum[row2][col1 - 1] - preSum[row1 - 1][col2] + preSum[row1 - 1][col1 - 1];
    }
}
相关推荐
.生产的驴21 分钟前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV28 分钟前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
知来者逆30 分钟前
计算机视觉——速度与精度的完美结合的实时目标检测算法RF-DETR详解
图像处理·人工智能·深度学习·算法·目标检测·计算机视觉·rf-detr
晨集30 分钟前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城33 分钟前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
阿让啊35 分钟前
C语言中操作字节的某一位
c语言·开发语言·数据结构·单片机·算法
এ᭄画画的北北35 分钟前
力扣-160.相交链表
算法·leetcode·链表
椰羊~王小美40 分钟前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
凯酱1 小时前
MyBatis-Plus分页插件的使用
java·tomcat·mybatis
程序员总部1 小时前
如何在IDEA中高效使用Test注解进行单元测试?
java·单元测试·intellij-idea