Find the largest area rectangular sub-matrix whose sum is equal to k in C++

C++Server Side ProgrammingProgramming

Suppose we have a 2D matrix mat and a value K, we have to find the longest rectangular submatrix whose sum is same as K.

So, if the input is like

28-56
-778-3
11-1443
-43110

And K = 9

then the output will be Top-Left point is (1, 0) and Bottom-Right point is (3, 2).

-778
11-144
-431

To solve this, we will follow these steps −

  • MAX := 100

  • Define a function sum_k(), this will take one array arr, start, end, n, k,

  • Define one map

  • sum := 0, maximum_length := 0

  • for initialize i := 0, when i < n, update (increase i by 1), do −

    • sum := sum + arr[i]

    • if sum is same as k, then −

      • maximum_length := i + 1

      • start := 0

      • end := i

    • if sum is not in map, then −

      • map[sum] := i

    • if (sum - k) is in map, then −

      • if maximum_length < (i - map[sum - k]), then −

        • maximum_length := i - map[sum - k]

        • start := map[sum - k] + 1

        • end := i

  • return true when maximum_length is not 0

  • From the main method, do the following −

  • row := row count of mat, col := column count of mat

  • Define an array temp of size: row.

  • Define an array final_point = {0,0,0,0}

  • maxArea := -inf

  • for initialize left := 0, when left < col, update (increase left by 1), do −

    • fill temp with 0

    • for initialize right := left, when right < col, update (increase right by 1), do −

      • for initialize i := 0, when i < row, update (increase i by 1), do −

        • temp[i] := temp[i] + mat[i, right]

      • sum := sum_k(temp, up, down, row, k)

      • area := (down - up + 1) * (right - left + 1)

      • if sum is non-zero and maxArea < area, then −

        • final_point[0] := up, final_point[1] := down

        • final_point[2] := left, final_point[3] := right

        • maxArea := area

    • if final_point is [0,0,0,0] and mat[0,0] is not k, then

      • return "No sub - matrix found"

  • display top-left point (final_point[0], final_point[2])

  • display bottom-right point (final_point[1], final_point[3])

  • display mat elements.

Example 

Let us see the following implementation to get better understanding −

 Live Demo

#include <bits/stdc++.h>
using namespace std;
const int MAX = 100;
bool sum_k(int arr[], int& start, int& end, int n, int k) {
   unordered_map<int, int> map;
   int sum = 0, maximum_length = 0;
   for (int i = 0; i < n; i++) {
      sum += arr[i];
      if (sum == k) {
         maximum_length = i + 1;
         start = 0;
         end = i;
      }
      if (map.find(sum) == map.end())
         map[sum] = i;
      if (map.find(sum - k) != map.end()) {
         if (maximum_length < (i - map[sum - k])) {
            maximum_length = i - map[sum - k];
            start = map[sum - k] + 1;
            end = i;
         }
      }
   }
   return (maximum_length != 0);
}
void sum_zero(vector<vector<int>> &mat, int k) {
   int row = mat.size();
   int col = mat[0].size();
   int temp[row], area;
   bool sum;
   int up, down;
   vector<int> final_point = {0,0,0,0};
   int maxArea = INT_MIN;
   for (int left = 0; left < col; left++) {
      memset(temp, 0, sizeof(temp));
      for (int right = left; right < col; right++) {
         for (int i = 0; i < row; i++)
            temp[i] += mat[i][right];
         sum = sum_k(temp, up, down, row, k);
         area = (down - up + 1) * (right - left + 1);
         if (sum && maxArea < area) {
            final_point[0] = up;
            final_point[1] = down;
            final_point[2] = left;
            final_point[3] = right;
            maxArea = area;
         }
      }
   }
   if (final_point[0] == 0 && final_point[1] == 0 && final_point[2] == 0 &&
   final_point[3] == 0 && mat[0][0] != k) {
      cout << "No sub-matrix found";
      return;
   }
   cout << "(Top, Left) Coordinate: " << "(" << final_point[0] << ", " << final_point[2] << ")" << endl;
   cout << "(Bottom, Right) Coordinate: " << "(" << final_point[1] << ", " << final_point[3] << ")" << endl;
   for (int j = final_point[0]; j <= final_point[1]; j++) {
      for (int i = final_point[2]; i <= final_point[3]; i++)
         cout << mat[j][i] << " ";
      cout << endl;
   }
}
main(){
   vector<vector<int>> v = {
      { 2, 8, -5, 6 },
      { -7, 7, 8, -3 },
      { 11, -14, 4, 3 },
      { -4, 3, 1, 10 }};
   sum_zero(v, 9);
}

Input

{{ 2, 8, -5, 6 },
{ -7, 7, 8, -3 },
{ 11, -14, 4, 3 },
{ -4, 3, 1, 10 }},
9

Output

(Top, Left) Coordinate: (1, 0)
(Bottom, Right) Coordinate: (3, 2)
-7 7 8
11 -14 4
-4 3 1
raja
Updated on 20-Aug-2020 07:25:23

Advertisements