剑指offer13:二维矩阵的数字之和

题目:
输入一个二维矩阵,如何计算给定左上角坐标和右下角坐标的子矩阵的数字之和?对于同一个二维矩阵,计算子矩阵的数字之和的函数可能由于输入不同的坐标而被反复调用多次。例如,输入下图中的二维矩阵,以及左上角坐标为(2,1)和右下角坐标(4,3)的子矩阵,该函数输出8。
在这里插入图片描述
分析:
直接采用蛮力解法,时间复杂度为O(mn),但是输入不同的坐标反复求不同子矩阵的数字之和,因此需要优化代码,尽可能快地实现子矩阵的数字求和。
在这里插入图片描述
看上图,想要求黄色部分的子矩阵数字之和需要绿色圈的部分减去两个红色圈的部分再加上一个蓝色圈部分(因为之前减掉了两次蓝色部分)。
预处理首先想办法创建辅助矩阵sums,该矩阵中的坐标(i,j)的数值是输入矩阵中从左上角坐标(0,0)到右下角坐标(i,j)的子矩阵数字之和。有了这个辅助矩阵求左上角(r1,c1),右下角(r2,c2)的子矩阵的数字之和就容易多了,该矩阵数字之和等于sums[r2][c2]-sums[r1-1][c2]-sums[r2][c1-1]+sums[r1-1][r2-1]。
现在的问题是如何生成矩阵sums,可以把从左上角坐标为(0,0)到右下角坐标为(i,j)的子矩阵的数字之和看成两部分组成,第一分部是左上角(0,0)到右下角坐标为(i-1,j)的子矩阵,该子矩阵的数字之和等于sums[i-1][j]。另一部分是输入矩阵中第i行从列号0到j的所有数字。(参见下图:蓝色部分(1部分)加绿色部分(2部分)等于红色部分)
在这里插入图片描述
主要就是通过以上思路来求解这道题,还需要特别注意:由于这个公式sums[r2][c2]-sums[r1-1][c2]-sums[r2][c1-1]+sums[r1-1][r2-1],r1和r2代表的是坐标,如果r1为0或r2为0,那么r1-1就是-1,r2-1也是-1,不再是有效数组了,因此在sums矩阵的最上面再加上一行,最左边再加上一列,这样就避免了下标为-1的情况。
代码和注解如下:

package com.wzc;

public class NumMatrix {
    private int[][] sums;
//    NumMatrix的构造函数用来做预处理,根据输入矩阵生成辅助矩阵sums,用两个嵌套循环因此
//    时间复杂度为O(mn),空间复杂度也为O(mn)。
    public  NumMatrix(int[][] matrix){
        if (matrix.length == 0||matrix[0].length == 0){
            return;
        }
//        为了防止出现下标为-1的情况,所以矩阵最上面增加一行,最左边增加一列,这样就
//        不用担心出现数组下标为-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;
            }
        }
    }
//    用来求子矩阵的数字之和,该函数只是从数组中读取几个数字做加减法,时间复杂度O(1)。
    public static int sumRegion(int rows1,int col1,int rows2,int col2){
        return sums[rows2+1][col2+1]-sums[rows1][col2+1]-sums[rows2+1][col1]+
                sums[rows1][col1];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

龙崎流河

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

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

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

打赏作者

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

抵扣说明:

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

余额充值