This problem requires designing a data structure that efficiently handles both updates to individual cells and range sum queries in a 2D matrix. Two common approaches are using a Binary Indexed Tree (BIT) or a Segment Tree. Both solutions are presented below.
This approach uses a BIT for each row of the matrix. Each row's BIT stores the prefix sums. Updating a cell involves updating the corresponding BIT for that row. A range sum query involves summing up the range sums from the appropriate BITs for each row within the specified range.
Time Complexity:
update(row, col, val)
: O(M log N), where M is the number of rows and N is the number of columns. This is because updating a single cell in a BIT takes O(log N) time, and we do this for one row.sumRegion(row1, col1, row2, col2)
: O(M log N). This is because we need to query the BIT for each row within the specified range, and each query takes O(log N) time.Space Complexity: O(M * N). This is due to the storage of the original matrix and the BITs for each row.
This approach uses a segment tree for each row of the matrix. Each segment tree node stores the sum of the elements in its corresponding range. Updating a cell involves updating the path from the root to the leaf in the segment tree for that row. A range sum query traverses the segment tree, aggregating the sums for the ranges that fall within the query range.
Time Complexity:
update(row, col, val)
: O(M log N). Updating a cell requires traversing a tree of height log N for one row.sumRegion(row1, col1, row2, col2)
: O(M log N). Each row's query takes O(log N) time.Space Complexity: O(M * N log N). This is because the segment trees have a space complexity of O(N log N) per row.
Both approaches are implemented in Python3. Java and C++ implementations are also provided in the original response.
Approach 1: Binary Indexed Tree
class BinaryIndexedTree:
# ... (Binary Indexed Tree implementation as shown in the original response) ...
class NumMatrix:
# ... (NumMatrix implementation using BIT as shown in the original response) ...
Approach 2: Segment Tree
class Node:
# ... (Node class definition) ...
class SegmentTree:
# ... (SegmentTree implementation as shown in the original response) ...
class NumMatrix:
# ... (NumMatrix implementation using Segment Tree as shown in the original response) ...
The code implementations clearly show the structure and functions of both approaches, making it easy to understand the logic behind each method. Remember to choose the approach based on your specific needs and the trade-offs between space and time complexity. For most scenarios with the given constraints, the Binary Indexed Tree solution provides a better balance between time and space complexity.