3

Given a 2-dimensional array of positive integers, find the subrectangle of size HxW with the largest sum. The sum of a rectangle is the sum of all the elements in that rectangle.

Input: A 2D array NxN with positive elements The HxW size of the subrectangle

Output: The submatrix of HxW size with the largest sum of its elements.

I've solved this using a brute-force method, however, I'm now looking for a better solution with better complexity (my brute-force method's complexity is O(n6)).

Saeid
  • 4,147
  • 7
  • 27
  • 43
drakerc
  • 139
  • 8
  • 1
    Isn't the subrectangle with maximum sum the original NxN array? You are saying it's all positive integers so the biggest sum is always going to be to sum all elements of the original array. – Amin J Oct 09 '16 at 01:26
  • The HxW subrectable is always smaller than the original NxN array. So for example given an 5x5 array, find the subarray sized 2x2 that has the biggest sum of elements - therefore I can't look for subarrays sized 5x5, it has to be the HxW size, not smaller, not bigger. – drakerc Oct 09 '16 at 09:57

1 Answers1

5

First create the cumulative sum of your matrix: O(n2)

Matrix
2 4 5 6
2 3 1 4
2 0 2 1

Cumulative sum
2 6  11 17
4 11 17 27
6 13 21 32

cumulative_sum(i,j) is the sum of all the elements in the submatrix (0:i,0:j). You can calculate the cumulative sum matrix using below logic:

cumulative_sum(i,j) = cumulative_sum(i-1,j) + cumulative_sum(i,j-1) - cumulative_sum(i-1,j-1) + matrix(i,j)

Using the cumulative sum matrix you can calculate sum of every sub-matrix in O(1):

calculating sum of submatrix (r1 ... r2 , c1 ... c2)
sum_sub = cumulative_sum(r2,c2) - cumulative_sum(r1-1,c2) - cumulative_sum(r2,c1-1) + cumulative_sum(r1-1,c1-1)

Inclusion-Exclusion

Then using two loops you can put the top-left of your HW rectangle on every point of the matrix and calculate the sum of that rectangle.

for r1=0->n_rows
   for c1=0->n_cols
       r2 = r1 + height - 1
       c2 = c1 + width - 1
       if valid(r1,c1,r2,c2) // doesn't exceed the original matrix
            sum_sub = ... // formula mentioned above
            best = max(sum_sub, best)
return best

This approach is in O(N2).

Here is the python implementation:

from copy import deepcopy

def findMaxSubmatrix(matrix, height, width):
    nrows = len(matrix)
    ncols = len(matrix[0])           

    cumulative_sum = deepcopy(matrix)

    for r in range(nrows):
        for c in range(ncols):
            if r == 0 and c == 0:
                cumulative_sum[r][c] = matrix[r][c]
            elif r == 0:
                cumulative_sum[r][c] = cumulative_sum[r][c-1] + matrix[r][c]
            elif c == 0:
                cumulative_sum[r][c] = cumulative_sum[r-1][c] + matrix[r][c]
            else:
                cumulative_sum[r][c] = cumulative_sum[r-1][c] + cumulative_sum[r][c-1] - cumulative_sum[r-1][c-1] + matrix[r][c]

    best = 0
    best_pos = None

    for r1 in range(nrows):
        for c1 in range(ncols):
            r2 = r1 + height - 1
            c2 = c1 + width - 1
            if r2 >= nrows or c2 >= ncols:
                continue
            if r1 == 0 and c1 == 0:
                sub_sum = cumulative_sum[r2][c2]
            elif r1 == 0:
                sub_sum = cumulative_sum[r2][c2] - cumulative_sum[r2][c1-1]
            elif c1 == 0:
                sub_sum = cumulative_sum[r2][c2] - cumulative_sum[r1-1][c2]
            else:
                sub_sum = cumulative_sum[r2][c2] - cumulative_sum[r1-1][c2] - cumulative_sum[r2][c1-1] + cumulative_sum[r1-1][c1-1]
            if best < sub_sum:
                best_pos = r1,c1
                best = sub_sum

    print "maximum sum is:", best
    print "top left corner on:", best_pos


matrix = [ [2,4,5,6],
           [2,3,1,4],
           [2,0,2,1] ]
findMaxSubmatrix(matrix,2,2)

output

maximum sum is: 16
top left corner on: (0, 2)
Saeid
  • 4,147
  • 7
  • 27
  • 43
  • (reference: the "cumulative sum array" is also called "summed-area table". [Wikipedia](https://en.wikipedia.org/wiki/Summed_area_table). – user202729 Feb 12 '21 at 06:21