题目描述
给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。
上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/range-sum-query-2d-immutable/
示例1:
给定 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 。
解题思路
关键词:
- 矩阵元素和
- 矩阵不变
思路:
- 法①:第一反应是通过
切片
的方法,找到目标后逐行遍历求和。 切片
简单,但本质时间换空间,时间效率很低。- 法②:明显的
动态规划
问题,创建一个dp矩阵,表中每个元素记录matrix 矩阵中元素至(0, 0)的矩阵内所有元素之和
。
matrix 矩阵:
a | b |
c | d |
dp 矩阵:
0 | 0 | 0 |
0 | A(= a) | B(= a + b = A + b) |
0 | C(= a + c = A + c) | D(= a + b + c + d = B + C - A + d) |
- 有了记录元素和的表,再求目标矩阵值则可以通过类似
D - C - B + A
的方式求得。
我的代码
法①:
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):
res += sum(self.matrix[i][col1:col2+1])
return res
法②:
class NumMatrix:
def __init__(self, matrix): # 构造dp列表,存储”(0, 0)至(m, n)数据和“的信息
if not matrix or not matrix[0]: # 如果是0行或者0列,则直接返回
return
self.dp_matrix = [[0] * (len(matrix[0]) + 1) for _ in range(len(matrix) + 1)] # 创建空列表:dp
for i in range(len(matrix)):
for j in range(len(matrix[0])):
self.dp_matrix[i + 1][j + 1] = self.dp_matrix[i][j + 1] + self.dp_matrix[i + 1][j] \
- self.dp_matrix[i][j] + matrix[i][j] # 存储“(0, 0)至(m, n)数据和”信息
def sumRegion(self, row1, col1, row2, col2): # 利用dp列表,求出目标区域的”数据和“
return self.dp_matrix[row2 + 1][col2 + 1] - self.dp_matrix[row1][col2 + 1] - self.dp_matrix[row2 + 1][col1] \
+ self.dp_matrix[row1][col1]
时间复杂度:构造函数的时间复杂度是O(m∗n)。
空间复杂度:即,dp矩阵,是O(m∗n)。
心得
动态规划
的编码还不熟练,能瞬间想到dp的过程,但常需花费一段时间去思考如何编码,需要继续训练。