Given a 2D matrix matrix
, handle multiple queries of the following type:
matrix
inside the rectangle defined by its upper left corner (row1, col1)
and lower right corner (row2, col2)
.Implement the NumMatrix
class:
NumMatrix(int[][] matrix)
Initializes the object with the integer matrix matrix
.int sumRegion(int row1, int col1, int row2, int col2)
Returns the sum of the elements of matrix
inside the rectangle defined by its upper left corner (row1, col1)
and lower right corner (row2, col2)
.You must design an algorithm where sumRegion
works on O(1)
time complexity.
Example 1:
Input ["NumMatrix", "sumRegion", "sumRegion", "sumRegion"] [[[[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]]], [2, 1, 4, 3], [1, 1, 2, 2], [1, 2, 2, 4]] Output [null, 8, 11, 12] Explanation NumMatrix numMatrix = new 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]]); numMatrix.sumRegion(2, 1, 4, 3); // return 8 (i.e sum of the red rectangle) numMatrix.sumRegion(1, 1, 2, 2); // return 11 (i.e sum of the green rectangle) numMatrix.sumRegion(1, 2, 2, 4); // return 12 (i.e sum of the blue rectangle)
Constraints:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 200
-104 <= matrix[i][j] <= 104
0 <= row1 <= row2 < m
0 <= col1 <= col2 < n
104
calls will be made to sumRegion
.Given a 2D matrix matrix
, implement the NumMatrix
class to handle multiple queries. Each query calculates the sum of elements within a specified rectangular region defined by its top-left and bottom-right corners. The sumRegion
method should have O(1) time complexity.
This solution leverages the concept of a two-dimensional prefix sum. A prefix sum array s
stores the cumulative sum of elements up to a given row and column. By calculating the prefix sum array once during initialization, we can efficiently answer sum region queries in O(1) time.
Prefix Sum Formula:
The key to this approach is understanding how to calculate the sum of a rectangular region using the prefix sum array. The sum of a rectangle with top-left corner (row1, col1)
and bottom-right corner (row2, col2)
is given by:
s[row2 + 1][col2 + 1] - s[row2 + 1][col1] - s[row1][col2 + 1] + s[row1][col1]
Algorithm:
Initialization (__init__
or constructor
):
s
with dimensions one larger than the input matrix matrix
. This allows for easier indexing starting from 1.s[0][j]
and s[i][0]
to 0 for all valid i
and j
.matrix[i][j]
, calculate the prefix sum:
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + matrix[i][j]
Query (sumRegion
):
row1
, col1
, row2
, and col2
, directly apply the prefix sum formula to obtain the region's sum.Time and Space Complexity:
sumRegion
query: O(1)The following code demonstrates the solution in various programming languages:
Python:
class NumMatrix:
def __init__(self, matrix: List[List[int]]):
m, n = len(matrix), len(matrix[0])
self.s = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(m):
for j in range(n):
self.s[i + 1][j + 1] = self.s[i + 1][j] + self.s[i][j + 1] - self.s[i][j] + matrix[i][j]
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
return self.s[row2 + 1][col2 + 1] - self.s[row2 + 1][col1] - self.s[row1][col2 + 1] + self.s[row1][col1]
Java:
class NumMatrix {
private int[][] s;
public NumMatrix(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
s = new int[m + 1][n + 1];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + matrix[i][j];
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
return s[row2 + 1][col2 + 1] - s[row2 + 1][col1] - s[row1][col2 + 1] + s[row1][col1];
}
}
(Other languages like C++, JavaScript, Go, TypeScript, Kotlin, and Rust would follow a similar structure, adapting the syntax and data structures accordingly.)
This detailed explanation and code examples should help you understand the solution to this LeetCode problem effectively. Remember that the key is the efficient pre-computation of the prefix sum array to enable O(1) query time.