Start learning free

LESSON 237 OF 410 · PARTIAL SUMS #2

Maximum Sum Submatrix III in JavaScript (Time Complexity: O(m^2 * n^2))

Practice O(n2 * m) Read the full explanation

Given a m x n grid filled with integers, find the submatrix with maximum sum among all submatrices.

Example:

Input:
[
  [ 1,  -9, -10,  1],
  [-1,  10,  10,  1],
  [ 0,   9,   9, -9],
  [-1,  -1,  -1, -1]
]
Output: 38
Explanation: Submatrix [[10, 10], [9, 9]]
STEP 1 OF 21
    Ctrl + Enter to check

    JAVASCRIPT · PARTIAL SUMS #2

    Maximum Sum Submatrix in JavaScript, explained

    Understanding the Problem

    The core challenge of this problem is to find the submatrix within a given m x n grid that has the maximum sum. This problem is significant in various applications such as image processing, financial analysis, and more. A common pitfall is to assume that the submatrix must be of a fixed size, but it can be of any size within the given matrix.

    Approach

    To solve this problem, we can use a dynamic programming approach combined with the concept of prefix sums. Here's a step-by-step breakdown:

    Naive Solution

    The naive solution involves checking all possible submatrices and calculating their sums. This approach is not optimal due to its high time complexity of O(m^3 * n^3).

    Optimized Solution

    We can optimize the solution by using prefix sums to reduce the time complexity to O(m^2 * n^2). The idea is to precompute the sum of elements in submatrices starting from the top-left corner to any point (i, j) in the matrix. This allows us to quickly calculate the sum of any submatrix using these precomputed sums.

    Algorithm

    1. Compute the prefix sum matrix.

    2. Iterate over all possible pairs of rows.

    3. For each pair of rows, use a sliding window technique to find the maximum sum subarray for the columns between these rows.

    Code Implementation

    // Function to find the maximum sum submatrix
    function maxSumSubmatrix(matrix) {
        const m = matrix.length;
        const n = matrix[0].length;
        
        // Step 1: Compute the prefix sum matrix
        const prefixSum = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
        for (let i = 1; i <= m; i++) {
            for (let j = 1; j <= n; j++) {
                prefixSum[i][j] = matrix[i - 1][j - 1] + prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1];
            }
        }
        
        let maxSum = -Infinity;
        
        // Step 2: Iterate over all pairs of rows
        for (let row1 = 1; row1 <= m; row2++) {
            for (let row2 = row1; row2 <= m; row2++) {
                let currentSum = 0;
                let maxSubarraySum = -Infinity;
                
                // Step 3: Use sliding window to find the maximum sum subarray for columns between row1 and row2
                for (let col = 1; col <= n; col++) {
                    const submatrixSum = prefixSum[row2][col] - prefixSum[row1 - 1][col];
                    currentSum = Math.max(submatrixSum, currentSum + submatrixSum);
                    maxSubarraySum = Math.max(maxSubarraySum, currentSum);
                }
                
                maxSum = Math.max(maxSum, maxSubarraySum);
            }
        }
        
        return maxSum;
    }
    
    // Example usage
    const matrix = [
        [1, -9, -10, 1],
        [-1, 10, 10, 1],
        [0, 9, 9, -9],
        [-1, -1, -1, -1]
    ];
    
    console.log(maxSumSubmatrix(matrix)); // Output: 38
    

    Complexity Analysis

    The time complexity of this approach is O(m^2 * n^2) due to the nested loops iterating over pairs of rows and columns. The space complexity is O(m * n) for the prefix sum matrix.

    Edge Cases

    Potential edge cases include:

    • Matrix with all negative numbers.
    • Matrix with a single row or column.
    • Matrix with all zeros.

    Each of these cases should be tested to ensure the algorithm handles them correctly.

    Testing

    To test the solution comprehensively, consider the following test cases:

    • Simple cases with small matrices.
    • Large matrices with mixed positive and negative numbers.
    • Edge cases as mentioned above.

    Using a testing framework like Jest can help automate and manage these tests effectively.

    Thinking and Problem-Solving Tips

    When approaching such problems, it's essential to:

    • Break down the problem into smaller, manageable parts.
    • Consider different approaches and their trade-offs.
    • Practice similar problems to build familiarity with common patterns and techniques.

    Conclusion

    Finding the maximum sum submatrix is a classic problem that can be efficiently solved using dynamic programming and prefix sums. Understanding and implementing this solution helps build a strong foundation in algorithmic problem-solving.

    Additional Resources

    For further reading and practice, consider the following resources:

    Keep going with JavaScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free