Description
Given a m * n matrix mat and an integer K, return a matrix answer where each answer[i][j] is the sum of all elements mat[r][c] for i - K <= r <= i + K, j - K <= c <= j + K, and (r, c) is a valid position in the matrix.
Constraints:
• m == mat.length
• n == mat[i].length
• 1 <= m, n, K <= 100
• 1 <= mat[i][j] <= 100
Example
Example 1:
Input: mat = [[1,2,3],[4,5,6],[7,8,9]], K = 1
Output: [[12,21,16],[27,45,33],[24,39,28]]
Example 2:
Input: mat = [[1,2,3],[4,5,6],[7,8,9]], K = 2
Output: [[45,45,45],[45,45,45],[45,45,45]]
Submissions
根据题意可以理解为是一个区域前缀和的问题,所以首先求出矩阵的前缀和,然后根据题目要求,求出子数组的元素和。i - K <= r <= i + K, j - K <= c <= j + K是指以(i - K,j - K )为左上角,以( i + K,j + K)为右下角中间的所有子数组的和。
我们用dp[i][j]记录原矩阵从[0][0]到[i][j]的这个矩形区域的和,通过使用dp中的元素进行计算可以得到原矩阵中任意矩形区域的和。原矩阵中的点加减K得到的矩形框可能会超出原矩阵区域,所以要对矩形框设限,
r1=max(i-K,0)
c1=max(j-K,0)
r2=min(m-1,i+K)
c2=min(n-1,j+K)
此即为矩形框左上角点和右下角点的横纵坐标。
需要求和的原矩阵的矩形区域就相当于res[i][j]=dp[r2+1][c2+1]-dp[r2+1][c1]-dp[r1][c2+1]+dp[r1][c1],其中res[i][j]表示(i,j)位置的区域前缀和。
实现代码如下:
class Solution:
def matrixBlockSum(self, mat: List[List[int]], K: int) -> List[List[int]]:
m, n = len(mat), len(mat[0])
dp = [[0] * (n+1) for _ in range(m+1)]
res = [[0] *(n) for _ in range(m)]
for i in range(1,m+1):
for j in range(1,n+1):
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+mat[i-1][j-1]
for i in range(m):
for j in range(n):
r1=max(i-K,0)
c1=max(j-K,0)
r2=min(m-1,i+K)
c2=min(n-1,j+K)
res[i][j]=dp[r2+1][c2+1]-dp[r2+1][c1]-dp[r1][c2+1]+dp[r1][c1]
return res