题目:
给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。
上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。
示例:
给定 matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5]
]
sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12
提示:
你可以假设矩阵不可变。
会多次调用 sumRegion 方法。
你可以假设 row1 ≤ row2 且 col1 ≤ col2 。
题目链接:
https://leetcode-cn.com/problems/range-sum-query-2d-immutable
解题思路:
1.先遍历行,行是从row1到row2,再遍历每一行的每一个元素,元素是从col1到col2
2.将遍历的元素相加即可。
代码:
class NumMatrix:
def __init__(self, matrix):
self.matrix = matrix
def sumRegion(self, row1, col1, row2, col2):
res = 0
for i in range(row1,row2+1):
for j in range(col1,col2+1):
res += self.matrix[i][j]
return res
s = NumMatrix([[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]])
print(s.sumRegion(2,1,4,3))
方法二:
做这种初始化一次、检索多次的题目的秘诀:在初始化的时候做预处理。
今天的每日一题让求二维数组中某个子矩形区域的和。很容易看出,今天的题目是 303. 区域和检索 - 数组不可变 的升级版。
同样地,今天的题目仍然用 preSum(前缀和)求解,包括两个步骤。
步骤一:求 preSum
我们先从如何求出二维空间的 preSum[i][j]。
我们定义 preSum[i][j]preSum[i][j] 表示 从 [0,0][0,0] 位置到 [i,j][i,j] 位置的子矩形所有元素之和。
可以用下图帮助理解:
S(O, D) = S(O, C) + S(O, B) - S(O, A) + D
S(O,D)=S(O,C)+S(O,B)−S(O,A)+D
减去 S(O, A)S(O,A) 的原因是 S(O, C)S(O,C) 和 S(O, B)S(O,B) 中都有 S(O, A)S(O,A),即加了两次 S(O, A)S(O,A),所以需要减去一次 S(O, A)S(O,A)。
如果用 preSum 表示的话,对应了以下的递推公式:
preSum[i + 1][j + 1] = preSum[i][j + 1] + preSum[i + 1][j] - preSum[i][j] + matrix[i][j]
preSum[i+1][j+1]=preSum[i][j+1]+preSum[i+1][j]−preSum[i][j]+matrix[i][j]
步骤二:根据 preSum 求子矩形面积
前面已经求出了数组中从 [0,0][0,0] 位置到 [i,j][i,j] 位置的 preSum。下面要利用 preSum[i][j]preSum[i][j] 来快速求出任意子矩形的面积。
同样利用一张图来说明:
S(A, D) = S(O, D) - S(O, E) - S(O, F) + S(O, G)
S(A,D)=S(O,D)−S(O,E)−S(O,F)+S(O,G)
加上子矩形 S(O, G)S(O,G) 面积的原因是 S(O, E)S(O,E) 和 S(O, F)S(O,F) 中都有 S(O, G)S(O,G),即减了两次 S(O, G)S(O,G),所以需要加上一次 S(O, G)S(O,G)。
如果要求 [row1, col1][row1,col1] 到 [row2, col2][row2,col2] 的子矩形的面积的话,用 preSum 对应了以下的递推公式:
preSum[row2][col2] - preSum[row2][col1 - 1] - preSum[row1 - 1][col2] + preSum[row1 - 1][col1 - 1]
preSum[row2][col2]−preSum[row2][col1−1]−preSum[row1−1][col2]+preSum[row1−1][col1−1]
代码
下面代码实现的时候,使用的 preSum 比原矩阵 matrix 多了一行一列,是为了让第 0 行与第 0 列的元素也能使用上面的递推公式。如果 preSum 矩阵大小和 martix 大小相等,则需要对第 0 行与第 0 列特殊判断。
class NumMatrix:
def __init__(self, matrix):
if not matrix or not matrix[0]:
M, N = 0, 0
else:
M, N = len(matrix), len(matrix[0])
self.preSum = [[0] * (N + 1) for _ in range(M + 1)]
for i in range(M):
for j in range(N):
self.preSum[i + 1][j + 1] = self.preSum[i][j + 1] + self.preSum[i + 1][j] - self.preSum[i][j] + matrix[i][j]
def sumRegion(self, row1, col1, row2, col2):
return self.preSum[row2 + 1][col2 + 1] - self.preSum[row2 + 1][col1] - self.preSum[row1][col2 + 1] + self.preSum[row1][col1]
s = NumMatrix([[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]])
print(s.sumRegion(2,1,4,3))
作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/range-sum-query-2d-immutable/solution/ru-he-qiu-er-wei-de-qian-zhui-he-yi-ji-y-6c21/