03. 2D Difference Array

โœ… GFG solution to the 2D Difference Array problem: efficiently apply multiple range updates on 2D matrix using difference array technique with 2D prefix sum optimization. ๐Ÿš€

The problem can be found at the following link: ๐Ÿ”— Question Link

๐Ÿงฉ Problem Description

You are given a 2D integer matrix mat[][] of size n ร— m and a list of q operations opr[][]. Each operation is represented as an array [v, r1, c1, r2, c2], where:

  • v is the value to be added

  • (r1, c1) is the top-left cell of a submatrix

  • (r2, c2) is the bottom-right cell of the submatrix (inclusive)

For each of the q operations, add v to every element in the submatrix from (r1, c1) to (r2, c2). Return the final matrix after applying all operations.

๐Ÿ“˜ Examples

Example 1

Input: mat[][] = [[1, 2, 3],    opr[][] = [[2, 0, 0, 1, 1], [-1, 1, 0, 2, 2]]
                  [1, 1, 0],
                  [4,-2, 2]]
Output: [[3, 4, 3],
         [2, 2, -1],
         [3, -3, 1]]
Explanation: 
- First operation: Add 2 to submatrix from (0,0) to (1,1)
- Second operation: Add -1 to submatrix from (1,0) to (2,2)

๐Ÿ”’ Constraints

  • $1 \le n \times m, q \le 10^5$

  • $0 \le r1 \le r2 \le n - 1$

  • $0 \le c1 \le c2 \le m - 1$

  • $-10^4 \le \text{mat}[i][j], v \le 10^4$

โœ… My Approach

The optimal approach uses the 2D Difference Array technique combined with 2D Prefix Sum to efficiently handle multiple range update operations:

2D Difference Array + 2D Prefix Sum

  1. Initialize Difference Matrix:

    • Create a difference matrix d[][] of size (n+1) ร— (m+1) initialized with zeros.

    • This extra padding helps avoid boundary checks during operations.

  2. Apply Range Updates:

    • For each operation [v, r1, c1, r2, c2], use the 4-point technique:

      • Add v at d[r1][c1] (top-left corner)

      • Subtract v at d[r1][c2+1] (right boundary)

      • Subtract v at d[r2+1][c1] (bottom boundary)

      • Add v at d[r2+1][c2+1] (bottom-right corner)

  3. Compute 2D Prefix Sum:

    • Convert difference array to actual values using 2D prefix sum:

    • d[i][j] = d[i][j] + d[i-1][j] + d[i][j-1] - d[i-1][j-1]

    • This applies inclusion-exclusion principle for 2D arrays.

  4. Apply to Original Matrix:

    • Add the computed difference values to the original matrix elements.

  5. Return Result:

    • The modified matrix contains all range updates applied efficiently.

๐Ÿ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(q + nร—m), where q is the number of operations and nร—m is the matrix size. We process each operation in O(1) time and then perform a single pass through the matrix for 2D prefix sum computation.

  • Expected Auxiliary Space Complexity: O(nร—m), as we create a difference matrix of size (n+1)ร—(m+1) to store the difference values before applying them to the original matrix.

๐Ÿง‘โ€๐Ÿ’ป Code (C++)

class Solution {
public:
    vector<vector<int>> applyDiff2D(vector<vector<int>>& mat, vector<vector<int>>& opr) {
        int n = mat.size(), m = mat[0].size();
        vector<vector<int>> d(n + 1, vector<int>(m + 1, 0));
        
        for (auto& q : opr) {
            int v = q[0], r1 = q[1], c1 = q[2], r2 = q[3], c2 = q[4];
            d[r1][c1] += v;
            d[r1][c2 + 1] -= v;
            d[r2 + 1][c1] -= v;
            d[r2 + 1][c2 + 1] += v;
        }
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (i) d[i][j] += d[i - 1][j];
                if (j) d[i][j] += d[i][j - 1];
                if (i && j) d[i][j] -= d[i - 1][j - 1];
                mat[i][j] += d[i][j];
            }
        }
        return mat;
    }
};
โšก View Alternative Approaches with Code and Analysis

๐Ÿ“Š 2๏ธโƒฃ Separate Prefix Sum Approach

๐Ÿ’ก Algorithm Steps:

  1. Create difference matrix and apply 4-point technique for all operations.

  2. Compute row-wise prefix sums first across all rows.

  3. Compute column-wise prefix sums to get final difference values.

  4. Add difference matrix to original matrix for final result.

class Solution {
public:
    vector<vector<int>> applyDiff2D(vector<vector<int>>& mat, vector<vector<int>>& opr) {
        int n = mat.size(), m = mat[0].size();
        vector<vector<int>> diff(n, vector<int>(m, 0));
        
        for (auto& op : opr) {
            int val = op[0], r1 = op[1], c1 = op[2], r2 = op[3], c2 = op[4];
            diff[r1][c1] += val;
            if (c2 + 1 < m) diff[r1][c2 + 1] -= val;
            if (r2 + 1 < n) diff[r2 + 1][c1] -= val;
            if (r2 + 1 < n && c2 + 1 < m) diff[r2 + 1][c2 + 1] += val;
        }
        
        for (int i = 0; i < n; i++)
            for (int j = 1; j < m; j++)
                diff[i][j] += diff[i][j - 1];
        
        for (int j = 0; j < m; j++)
            for (int i = 1; i < n; i++)
                diff[i][j] += diff[i - 1][j];
        
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                mat[i][j] += diff[i][j];
        
        return mat;
    }
};

๐Ÿ“ Complexity Analysis:

  • Time: โฑ๏ธ O(q + nร—m) - q operations + matrix traversal

  • Auxiliary Space: ๐Ÿ’พ O(nร—m) - Separate difference matrix

๐Ÿ“Š 3๏ธโƒฃ Optimized Single Pass Approach

๐Ÿ’ก Algorithm Steps:

  1. Create difference matrix and apply all range operations using 4-point updates.

  2. Combine row and column prefix sum computation in single traversal.

  3. Use inclusion-exclusion principle for 2D prefix sum calculation.

  4. Apply computed differences to original matrix in same pass.

class Solution {
public:
    vector<vector<int>> applyDiff2D(vector<vector<int>>& mat, vector<vector<int>>& opr) {
        int n = mat.size(), m = mat[0].size();
        vector<vector<long long>> d(n + 1, vector<long long>(m + 1, 0));
        
        for (const auto& op : opr) {
            long long v = op[0];
            int r1 = op[1], c1 = op[2], r2 = op[3], c2 = op[4];
            d[r1][c1] += v;
            d[r1][c2 + 1] -= v;
            d[r2 + 1][c1] -= v;
            d[r2 + 1][c2 + 1] += v;
        }
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                d[i][j] += (i ? d[i-1][j] : 0) + (j ? d[i][j-1] : 0) - (i && j ? d[i-1][j-1] : 0);
                mat[i][j] += d[i][j];
            }
        }
        return mat;
    }
};

๐Ÿ“ Complexity Analysis:

  • Time: โฑ๏ธ O(q + nร—m) - Single pass optimization

  • Auxiliary Space: ๐Ÿ’พ O(nร—m) - Difference matrix with overflow protection

๐Ÿ“Š 4๏ธโƒฃ Naive Brute Force Approach

๐Ÿ’ก Algorithm Steps:

  1. For each operation, iterate through the entire submatrix range.

  2. Add the value v to each cell in the specified rectangular region.

  3. Continue for all operations sequentially.

  4. Return the modified matrix.

class Solution {
public:
    vector<vector<int>> applyDiff2D(vector<vector<int>>& mat, vector<vector<int>>& opr) {
        for (auto& op : opr) {
            int val = op[0], r1 = op[1], c1 = op[2], r2 = op[3], c2 = op[4];
            for (int i = r1; i <= r2; i++) {
                for (int j = c1; j <= c2; j++) {
                    mat[i][j] += val;
                }
            }
        }
        return mat;
    }
};

๐Ÿ“ Complexity Analysis:

  • Time: โฑ๏ธ O(q ร— n ร— m) - For each operation, traverse submatrix

  • Auxiliary Space: ๐Ÿ’พ O(1) - No extra space needed

โš ๏ธ Why Not This Approach?

  • Extremely slow for large matrices and many operations.

  • Time complexity can become O(q ร— n ร— m) in worst case.

  • Not suitable for competitive programming constraints.

๐Ÿ†š ๐Ÿ” Comparison of Approaches

๐Ÿš€ Approach

โฑ๏ธ Time Complexity

๐Ÿ’พ Space Complexity

โœ… Pros

โš ๏ธ Cons

๐Ÿ” 2D Difference Array

๐ŸŸข O(q + nร—m)

๐ŸŸก O(nร—m)

๐Ÿš€ Single traversal, optimal

๐Ÿ”ง Complex index handling

๐Ÿ”„ Separate Prefix

๐ŸŸข O(q + nร—m)

๐ŸŸก O(nร—m)

๐Ÿ“– Clear logic separation

๐ŸŒ Multiple matrix passes

๐Ÿ”‘ Single Pass

๐ŸŸข O(q + nร—m)

๐ŸŸก O(nร—m)

โญ Overflow protection

๐Ÿงฎ Complex prefix calculation

๐Ÿ’€ Brute Force

๐Ÿ”ด O(q ร— n ร— m)

๐ŸŸข O(1)

๐Ÿ“ Simple to understand

โฐ Extremely slow for large inputs

๐Ÿ† Best Choice Recommendation

๐ŸŽฏ Scenario

๐ŸŽ–๏ธ Recommended Approach

๐Ÿ”ฅ Performance Rating

๐Ÿ… Optimal performance needed

๐Ÿฅ‡ 2D Difference Array

โ˜…โ˜…โ˜…โ˜…โ˜…

๐Ÿ“– Readability priority

๐Ÿฅˆ Separate Prefix

โ˜…โ˜…โ˜…โ˜…โ˜†

๐ŸŽฏ Large values/overflow risk

๐Ÿ… Single Pass

โ˜…โ˜…โ˜…โ˜…โ˜…

๐ŸŽ“ Learning/educational purposes

๐ŸŽ–๏ธ Brute Force

โ˜…โ˜…โ˜†โ˜†โ˜†

โ˜• Code (Java)

class Solution {
    public ArrayList<ArrayList<Integer>> applyDiff2D(int[][] mat, int[][] opr) {
        int n = mat.length, m = mat[0].length;
        long[][] d = new long[n + 1][m + 1];
        
        for (int[] op : opr) {
            int v = op[0], r1 = op[1], c1 = op[2], r2 = op[3], c2 = op[4];
            d[r1][c1] += v;
            d[r1][c2 + 1] -= v;
            d[r2 + 1][c1] -= v;
            d[r2 + 1][c2 + 1] += v;
        }
        
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            ArrayList<Integer> row = new ArrayList<>();
            for (int j = 0; j < m; j++) {
                if (i > 0) d[i][j] += d[i - 1][j];
                if (j > 0) d[i][j] += d[i][j - 1];
                if (i > 0 && j > 0) d[i][j] -= d[i - 1][j - 1];
                row.add(mat[i][j] + (int)d[i][j]);
            }
            res.add(row);
        }
        return res;
    }
}

๐Ÿ Code (Python)

class Solution:
    def applyDiff2D(self, mat, opr):
        n, m = len(mat), len(mat[0])
        d = [[0] * (m + 1) for _ in range(n + 1)]
        
        for v, r1, c1, r2, c2 in opr:
            d[r1][c1] += v
            d[r1][c2 + 1] -= v
            d[r2 + 1][c1] -= v
            d[r2 + 1][c2 + 1] += v
        
        for i in range(n):
            for j in range(m):
                if i: d[i][j] += d[i - 1][j]
                if j: d[i][j] += d[i][j - 1]
                if i and j: d[i][j] -= d[i - 1][j - 1]
                mat[i][j] += d[i][j]
        return mat

๐Ÿง  Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: ๐Ÿ“ฌ Any Questions?. Let's make this learning journey more collaborative!

โญ If you find this helpful, please give this repository a star! โญ


๐Ÿ“Visitor Count

Visitor counter

Last updated