二维数组区间求和

问题:

有一个任意的二维数组, 现要求写一个方法, 传入四个int类型的参数(row1, col1, row2, row2), 由这四个参数构成一个子二维数组, row1和col1是子二维数组的左上角元素的索引, row2和row2是子二维数组的右下角元素的索引. 现要求对这个子二维数组的元素求和.

简单理解的方法:
直接将范围内的值进行相加

图示:

代码演示:

public int sum(int row1, int col1, int row2, int col2) {
        int sum = 0;
        int length = nums.length;
        for (int i = row1; i <= row2; i++) {
            for (int j = col1; j <= col2; j++) {
                sum += nums[i][j];
            }
        }
        return sum;
    }

这个方法简单易理解, 但是有很多弊端, 如:当row2与row1差值很大, col2与col1差值很大, 程序循环的次数大大增加; 或是当这个方法被调用很多次的时候, 每一次都需要进行循环计算. 是的程序的执行效率大大降低

改进方法:

怎么解决这一问题呢, 我们可以提前计算好每一块区间的和将其存在一个二维数组中, 当调用sum()方法的时候, 只需要进行一些简单的加减计算即可得到结果,

先计算二维和数组:

计算方法图示:

图示:

代码演示:

public class Demo {
    static int[][] nums;

    public static void main(String[] args) {
        nums = new int[][]{
                {47, 21, 33, 57, 35},
                {68, 1, 17, 92, 78},
                {43, 91, 59, 86, 74},
                {1, 74, 48, 59, 2},
                {7, 56, 40, 63, 21},
                {65, 63, 18, 98, 75}};

        // 创建二维和数组的对象, 里面封装了二维数组指定区间求和的方法
        NumMatrix numMatrix = new NumMatrix(nums);

        // 打印原数组
        System.out.println("原数组");
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j < nums[0].length; j++) {
                System.out.printf("%-3d", nums[i][j]);
            }
            System.out.println();
        }

        numMatrix.show();// 打印二维和数组

        // 一定区间求和
        System.out.println("结果 = " + numMatrix.sumRegion(2, 1, 4, 2));
    }

    static class NumMatrix {
        int[][] sumMatrix;

        // 通过二维数组计算和二维数组
        public NumMatrix(int[][] matrix) {
            int row = matrix.length;
            int col = matrix[0].length;

            // 创建一个大小为原数组+1的二维数组, 目的是为了留出一行一列做辅助行列, 为方便计算
            sumMatrix = new int[row + 1][col + 1];
            // sumMatrix[i][0], sumMatrix[0][i]不进行使用只当作辅助空间
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    // 求和方式: 上和 + 左和 +  - 左上和(重复计算的部分) + 当前位置值
                    sumMatrix[i + 1][j + 1] = sumMatrix[i][j + 1] + sumMatrix[i + 1][j] - sumMatrix[i][j] + matrix[i][j];
                }
            }
        }

        // 打印二维和数组
        public void show(){
            System.out.println("二维和数组");
            for (int i = 1; i < sumMatrix.length; i++) {
                for (int j = 1; j < sumMatrix[0].length; j++) {
                    System.out.printf("%-5d", sumMatrix[i][j]);
                }
                System.out.println();
            }
        }

        public int sumRegion(int row1, int col1, int row2, int col2) {
            int row = sumMatrix.length - 1;
            int col = sumMatrix[0].length - 1;

            // 条件判断, 如果输入不合法返回 -1
            if (!(row1 >= 0 && col1 >= 0 && row2 < row && col2 < col)
                    || row1 > row2 || col1 > col2) {
                return -1;
            }

            // 区间求和:大区间 - 两块小区间 + 被重复减去区间
            return sumMatrix[row2 + 1][col2 + 1] - sumMatrix[row2 + 1][col1] - sumMatrix[row1][col2 + 1] + sumMatrix[row1][col1];
        }
    }
}
运行结果:

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Black—slience

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

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

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

打赏作者

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

抵扣说明:

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

余额充值