解法一:前缀和
先对矩阵求前缀和,有了前缀和之后就可以根据四部分的值求出任一矩阵的区域和。
注意考虑边界问题和源矩阵和前缀和矩阵之前的坐标关系。
class Solution {// 行数private int row;// 列数private int col;public int[][] matrixBlockSum(int[][] mat, int K) {row = mat.length;col = mat[0].length;// preSum[i][j]表示源矩阵中以(0,0)为左上角, (i-1,j-1)为右下角的矩阵内所有元素之和// 多开空间防止边界问题int[][] preSum = getPreSum(mat);int[][] ans = new int[row][col];int[] pos;for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {pos = getPosition(i, j, K);ans[i][j] = preSum[pos[2]][pos[3]] - preSum[pos[2]][pos[1]] - preSum[pos[0]][pos[3]]+ preSum[pos[0]][pos[1]];}}return ans;}/*** 求解算子对应前缀和矩阵的左上角和右下角坐标* @param x 算子在源矩阵中的行坐标* @param y 算子在源矩阵中的列坐标* @param k 算子规模* @return 算子对应前缀和矩阵的左上角和右下角坐标*/private int[] getPosition(int x, int y, int k) {int[] pos = new int[4];// 左上角行列坐标pos[0] = Math.max(0, x - k);pos[1] = Math.max(0, y - k);// 右下角行列坐标pos[2] = Math.min(row, x + k + 1);pos[3] = Math.min(col, y + k + 1);return pos;}/*** 求解矩阵的前缀和, ans[i][j]表示源矩阵中以(0,0)为左上角, (i-1,j-1)为右下角的矩阵内所有元素之和* @param mat 源矩阵* @return 前缀和矩阵*/private int[][] getPreSum(int[][] mat) {int[][] ans = new int[row + 1][col + 1];for (int i = 1; i <= row; ++i) {for (int j = 1; j <= col; ++j) {ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1] + mat[i - 1][j - 1];}}return ans;}}
