Range Sum Query 2D - Mutable - Solution & Explanation
Problem Statement
Given a 2D matrix matrix, handle multiple queries of the following types:
- Update the value of a cell in
matrix. - Calculate the sum of the elements of
matrixinside 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 matrixmatrix.void update(int row, int col, int val)Updates the value ofmatrix[row][col]to beval.int sumRegion(int row1, int col1, int row2, int col2)Returns the sum of the elements ofmatrixinside the rectangle defined by its upper left corner(row1, col1)and lower right corner(row2, col2).
Example 1:
Input ["NumMatrix", "sumRegion", "update", "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], [3, 2, 2], [2, 1, 4, 3]] Output [null, 8, null, 10] 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 left red rectangle) numMatrix.update(3, 2, 2); // matrix changes from left image to right image numMatrix.sumRegion(2, 1, 4, 3); // return 10 (i.e. sum of the right red rectangle)
Constraints:
m == matrix.lengthn == matrix[i].length1 <= m, n <= 200-1000 <= matrix[i][j] <= 10000 <= row < m0 <= col < n-1000 <= val <= 10000 <= row1 <= row2 < m0 <= col1 <= col2 < n- At most
5000calls will be made tosumRegionandupdate.
Approach Overview
Problem Overview: You need to design a data structure for a 2D matrix that supports two operations: updating a cell value and returning the sum of elements inside any rectangular submatrix. The challenge is handling frequent updates without recomputing sums for the entire region every time.
Approach 1: Brute Force Recalculation (Update O(1), Query O(m*n))
Store the matrix as-is. For every sumRegion(row1, col1, row2, col2) call, iterate through all cells inside the rectangle and accumulate the sum. Updates are trivial because you simply replace the value in the matrix. The downside is query performance: each query scans up to the entire matrix, giving O(m*n) time and O(1) extra space. This approach works for small matrices or when queries are rare.
Approach 2: 2D Prefix Sum with Rebuild (Update O(m*n), Query O(1))
Precompute a prefix sum matrix where each cell stores the sum of the rectangle from (0,0) to that position. A submatrix sum can then be computed using inclusion–exclusion in constant time. However, when a value changes, every affected prefix cell must be recomputed, which costs O(m*n). This approach favors scenarios with many queries but very few updates. It relies heavily on concepts from array traversal and matrix prefix sums.
Approach 3: 2D Binary Indexed Tree (Fenwick Tree) (Update O(log m * log n), Query O(log m * log n))
A 2D Binary Indexed Tree maintains cumulative sums in a hierarchical structure. Each update propagates changes to logarithmically many nodes, while queries aggregate prefix sums efficiently. To compute a rectangular region sum, query four prefix regions and combine them using inclusion–exclusion. Both updates and queries run in O(log m * log n) time with O(m*n) space. This structure handles frequent updates and queries efficiently, making it the practical optimal solution.
Approach 4: 2D Segment Tree (Update O(log m * log n), Query O(log m * log n))
A 2D Segment Tree organizes the matrix into nested segment trees across rows and columns. Each node represents the sum of a sub-rectangle. Updates propagate through both tree dimensions, and queries traverse only relevant nodes. Performance matches the Binary Indexed Tree with O(log m * log n) operations, but implementation complexity and memory overhead are higher. This approach is useful when you need flexible range operations beyond simple sums.
Recommended for interviews: Interviewers expect the 2D Binary Indexed Tree solution. The brute force version shows you understand the problem baseline, but the Fenwick Tree demonstrates strong data structure skills and the ability to optimize both updates and queries to logarithmic time.
Solution
Try this approach in the editor →Detailed Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Matrix Scan | Update O(1), Query O(m*n) | O(1) | Small matrices or when queries are very rare |
| 2D Prefix Sum (Rebuild on Update) | Update O(m*n), Query O(1) | O(m*n) | Many queries but almost no updates |
| 2D Binary Indexed Tree | Update O(log m * log n), Query O(log m * log n) | O(m*n) | General case with frequent updates and queries |
| 2D Segment Tree | Update O(log m * log n), Query O(log m * log n) | O(m*n) | When you need flexible range operations beyond simple sums |
Video Solution
Leetcode 308. Range Sum Query 2D - Mutable (binary index tree) • LetsCode • 621 views views
Watch 2 more video solutions →Frequently Asked Questions
Is Range Sum Query 2D - Mutable easy or hard?
Range Sum Query 2D - Mutable Python/Java solution
What is the best approach for Range Sum Query 2D - Mutable?
Is Range Sum Query 2D - Mutable asked at Google/Amazon/Meta?
What data structure is used in Range Sum Query 2D - Mutable?
What is the time complexity of Range Sum Query 2D - Mutable?
How to solve Range Sum Query 2D - Mutable in O(log m * log n)?
Ready to solve this problem?
Practice Range Sum Query 2D - Mutable with our built-in code editor and test cases.
Practice on FleetCode