二维子矩阵的数字之和

        不考虑时间复杂度,采取暴力法,两个for循环当然是可以求出二维矩阵的数字之和,时间复杂度是O(mn),mn分别是矩阵的行数和列数,但题目提到要被反复调用多次,所以应优化求和过程。

        同样是利用累加数组数字求子数组之和,不难想到,计算左上角坐标(r_1,c_2)、右下角坐标(r_2,c_2)的子矩阵之和可以用:左上角坐标(0,0)、右下角坐标(r_2,c_2)的子矩阵之和减去左上角坐标(0,0)、右下角坐标(r_1-1,c_2)的子矩阵之和减去左上角坐标(0,0)、右下角坐标(r_2,c_1-1)的子矩阵之和再加上左上角坐标(0,0)、右下角坐标(r_1-1,c_1-1)的子矩阵之和,四个矩阵计算。

        因此,可以先用一个辅助矩阵sums记录左上角坐标为(0,0)到每个右下角坐标的子矩阵之和。而计算sums[i][j]可以分成两部分计算,第一部分是左上角坐标(0,0),右下角坐标(i-1,j)的子矩阵之和,即sums[i-1][j],第二部分是输入矩阵第i行中第0列到第j列的数字之和。

        不过为了简化区域和的计算,会增加一行和一列,避免在计算部分和时要检查边界,使得代码更加简洁和高效,也就是初始化 sums 数组时,维度要比输入矩阵大1。具体来说,在sums数组中,sums[i][j] 表示从输入矩阵(0,0)到(i-1,j-1)的所有元素的和。因为原先sums[row2][col2] - sums[row1-1][col2] - sums[row2][col1-1] + sums[row1-1][col1-1]中row1-1和cow-1可能为负数,而这样在计算时,可以通过sums[i+1][j+1]表示从(0,0) 到(i,j)的部分和,即sums[row2 + 1][col2 + 1] - sums[row1][col2 + 1] - sums[row2 + 1][col1] + sums[row1][col1]。

public class NumMatrix {
    private int[][] sums;  // 存储从输入矩阵 (0,0) 到 (i,j) 的元素和

    // 构造函数,用于初始化 sums 数组
    public NumMatrix(int[][] matrix) {
        if (matrix.length == 0 || matrix[0].length == 0) {
            return;  // 处理空矩阵的情况
        }

        // 初始化 sums 数组,维度比原始矩阵大1
        sums = new int[matrix.length + 1][matrix[0].length + 1];

        // 使用动态规划计算部分和
        for (int i = 0; i < matrix.length; i++) {
            int rowSum = 0;
            for (int j = 0; j < matrix[0].length; j++) {
                rowSum += matrix[i][j];
                sums[i + 1][j + 1] = sums[i][j + 1] + rowSum;  // 存储部分和
            }
        }
    }

    // 计算给定区域 (row1, col1) 到 (row2, col2) 的元素和
    public int sumRegion(int row1, int col1, int row2, int col2) {
        // 利用预先计算好的 sums 数组计算区域和
        return sums[row2 + 1][col2 + 1] - sums[row1][col2 + 1] - sums[row2 + 1][col1] + sums[row1][col1];
    }
}

该算法用sumRegion求子矩阵的数字之和,每次调用时间复杂度为O(1),而构造函数预处理的时间复杂度是O(mn),空间复杂度是O(mn),mn分别是矩阵的行数和列数。

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不过是条河鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值