【每日一题】LeetCode 1314.矩阵区域和

现在开始一天一题了,防止老年痴呆 = =

一、题目大意

给你一个 m * n 的矩阵 mat 和一个整数 K ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:

i - K <= r <= i + K, j - K <= c <= j + K
(r, c) 在矩阵内。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/matrix-block-sum

二、题目思路以及AC代码

这题读懂题之后,我第一个思路就是暴力(好长时间没做题的后果),其实就是要算矩阵里针对每个位置,上下左右位移K的子矩阵的元素和,直接暴力的时间复杂度是O(N2K2),比较简单直接。

然后是想到了二维前缀和,即提前计算出一个矩阵prefix,其中prefix[i][j]代表以(i, j)为右下角,以(0, 0)为左上角的矩阵的元素和,这样的话,我们在计算区域和的时候,就可以直接利用以下公式进行计算。
在这里插入图片描述
当然, 这里要注意i+K,j+K,j-K-1,i-K-1的范围,不能超过矩阵大小,也不能小于0,这处理起来还是挺费劲的,可以参考我代码中的处理方式,在前缀和中添加冗余的行和列用于辅助处理。

下面给出AC代码:

class Solution {
public:
    vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int K) {
        vector<vector<int>> res;

        int rows = mat.size();
        if (rows == 0) return res;
        int cols = mat[0].size();
        if (cols == 0) return res;

        // 求前缀和
        int prefix[rows+1][cols+1];
        for (int i=0;i<=rows;i++) {
            for (int j=0;j<=cols;j++) {
                prefix[i][j] = 0;
            }
        }
        for (int i=1;i<=rows;i++) {
            for (int j=1;j<=cols;j++) {
                prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + mat[i-1][j-1];
            }
        }

        // 计算区域和
        for (int i=0;i<rows;i++) {
            vector<int> row;
            for (int j=0;j<cols;j++) {
                int up = max(-1, i - K - 1);
                int down = min(rows - 1, i + K);
                int left = max(-1, j - K - 1);
                int right = min(cols - 1, j + K);

                row.push_back(prefix[down+1][right+1] - prefix[down+1][left+1] - prefix[up+1][right+1] + prefix[up+1][left+1]);
            }
            res.push_back(row);
        }

        return res;
    }
};

你可能感兴趣的:(每日一题,leetcode,算法,前缀和)