leetcode304. 二维区域和检索 - 矩阵不可变(medium)
题目描述:
给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (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
代码模版(swift)
class NumMatrix {
init(_ matrix: [[Int]]) {
}
func sumRegion(_ row1: Int, _ col1: Int, _ row2: Int, _ col2: Int) -> Int {
}
}
解法1(一维数组前缀和)
类似的,我们可以用昨天每日一题前缀和解法,计算每一行前缀和,计算时按列前缀和相加。
class NumMatrix {
var matrixSum: [[Int]]!
init(_ matrix: [[Int]]) {
guard matrix.count > 0 else {
return
}
matrixSum = [[Int]](repeating: [Int](repeating: 0, count: matrix[0].count + 1), count: matrix.count)
for i in 0..<matrix.count {
for j in 0..<matrix[0].count {
matrixSum[i][j + 1] = matrixSum[i][j] + matrix[i][j]
}
}
}
func sumRegion(_ row1: Int, _ col1: Int, _ row2: Int, _ col2: Int) -> Int {
var ans = 0
for i in row1...row2 {
ans += (matrixSum[i][col2 + 1] - matrixSum[i][col1])
}
return ans
}
}
-
空间复杂度:O(n * m) 使用一个二维数组记录前缀和
-
时间复杂度:初始化O(n * m),区间求和O(N * n),N表示求和次数,n表示数组列数,每次求和均需要一趟线性遍历
运行结果:
运行耗时196ms,时间耗费较长,考虑优化代码以降低时间复杂度
解法2(二维前缀和)
思路:
图片摘自leetCode官方题解:
每一个二维数组总和可以由上述公式表示
指定区域的和可以由上述公式表示
class NumMatrix {
var matrixSum: [[Int]]!
init(_ matrix: [[Int]]) {
guard matrix.count > 0 else {
return
}
matrixSum = [[Int]](repeating: [Int](repeating: 0, count: matrix[0].count + 1), count: matrix.count + 1)
for i in 0..<matrix.count {
for j in 0..<matrix[0].count {
matrixSum[i + 1][j + 1] = matrixSum[i][j + 1] + matrixSum[i + 1][j] - matrixSum[i][j] + matrix[i][j]
}
}
}
func sumRegion(_ row1: Int, _ col1: Int, _ row2: Int, _ col2: Int) -> Int {
return matrixSum[row2 + 1][col2 + 1] - matrixSum[row1][col2 + 1] - matrixSum[row2 + 1][col1] + matrixSum[row1][col1]
}
}
为何可以用sumArr[j + 1] - sumArr[i]表示区间和?sumArr[j + 1]表示nums从0——j的和, sumArr[i]表示nums从0——(i-1)的和,两者相减去除了0——(i-1)的和,剩下的就是区间i——j的和
-
空间复杂度:O(n * m) 使用一个二维数组记录前缀和
-
时间复杂度:初始化O(n * m),区间求和O(1)
运行结果:
结语
leetcode这个月的主题大概就是前缀和了...
本文正在参与「掘金 2021 春招闯关活动」, 点击查看活动详情