CLOSE
🛠️ Settings

Problem Statement

Given a 2D matrix matrix, handle multiple queries of the following type:

  • Calculate the sum of the elements of 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.

LeetCode

https://leetcode.com/problems/range-sum-query-2d-immutable/description/

Constraints

m == matrix.length
n == matrix[i].length
1 <= m, n <= 200
-10^4 <= matrix[i][j] <= 10^4
0 <= row1 <= row2 < m
0 <= col1 <= col2 < n
At most 10^4 calls will be made to sumRegion.

Examples

Example 1:

image-556.png
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)

Different Approaches

1️⃣ Brute Force Approach (TLE)

🧠 Idea:

For each query, iterate through the submatrix and compute the sum.

💻 Code:

int sumRegion(int row1, int col1, int row2, int col2) {
    // Initialize sum to store the total sum of the submatrix
    int sum = 0;

    // Loop through each row from row1 to row2
    for (int i = row1; i <= row2; ++i) {
        // For the current row, loop through each column from col1 to col2
        for (int j = col1; j <= col2; ++j) {
            // Add the value at matrix[i][j] to the sum
            sum += matrix[i][j];
        }
    }

    // After summing all elements in the given region, return the result
    return sum;
}

Complexity Analysis:

  • Time Complexity:O(row2 - row 1 + 1) * (col2 - col1 + 1)
  • Space Complexity:O(1)

2️⃣ Row-wise Prefix Sum

🧠 Idea:

Store prefix sums for each row to speed up queries. You still iterate over rows, but reduce per-row work to O(1).

Code:

class NumMatrix {
    // 2D vector to store prefix sums of each row
    vector<vector<int>> rowPrefix;

public:
    // Constructor to initialize the prefix sum matrix
    NumMatrix(vector<vector<int>>& matrix) {
        int m = matrix.size();         // Number of rows
        int n = matrix[0].size();      // Number of columns

        // Copy original matrix to rowPrefix
        rowPrefix = matrix;

        // Calculate row-wise prefix sums
        for (int i = 0; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                // Add previous column value to current to make it cumulative
                rowPrefix[i][j] += rowPrefix[i][j - 1];
            }
        }
    }

    // Function to return the sum of elements inside the rectangle
    // defined by (row1, col1) as top-left and (row2, col2) as bottom-right
    int sumRegion(int row1, int col1, int row2, int col2) {
        int sum = 0;

        // Loop through each row from row1 to row2
        for (int i = row1; i <= row2; ++i) {
            // Use prefix sum to calculate the sum of columns from col1 to col2
            if (col1 == 0) {
                // If starting column is 0, just take prefix at col2
                sum += rowPrefix[i][col2];
            } else {
                // Else subtract prefix at col1 - 1 to get sum from col1 to col2
                sum += rowPrefix[i][col2] - rowPrefix[i][col1 - 1];
            }
        }

        return sum; // Return the total sum of the rectangle
    }
};

Complexity Analysis:

  • Time Complexity:
    • Preprocessing: O(m * n)
    • Query: O(row2 - row 1 + 1)
  • Space Complexity:O(m * n)

3️⃣ Prefix Sum (2D Preprocessing)

Code:

class NumMatrix {
    // 2D prefix sum matrix with extra row and column (1-based indexing)
    vector<vector<int>> prefix;

public:
    // Constructor to initialize the prefix sum matrix
    NumMatrix(vector<vector<int>>& matrix) {
        int m = matrix.size();          // Number of rows
        int n = matrix[0].size();       // Number of columns

        // Initialize prefix matrix with (m+1)x(n+1) size, all zeros
        // Extra row and column help avoid boundary checks later
        prefix = vector<vector<int>>(m + 1, vector<int>(n + 1, 0));

        // Build the prefix sum matrix
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                // Compute sum of submatrix from (0,0) to (i,j)
                prefix[i + 1][j + 1] = matrix[i][j]
                                     + prefix[i][j + 1]   // Above
                                     + prefix[i + 1][j]   // Left
                                     - prefix[i][j];      // Remove overlap (diagonal)
            }
        }
    }

    // Function to return sum of submatrix from (row1,col1) to (row2,col2)
    int sumRegion(int row1, int col1, int row2, int col2) {
        // Apply inclusion-exclusion principle to get the region sum in O(1)
        return prefix[row2 + 1][col2 + 1]   // Total up to bottom-right
             - prefix[row2 + 1][col1]       // Remove left block
             - prefix[row1][col2 + 1]       // Remove top block
             + prefix[row1][col1];          // Add overlap back
    }
};

📊 Complexity Analysis:

  • Time Complexity:
    • Preprocessing: O(m × n)
    • Time (query): O(1)
  • Space Complexity:O(m × n)