Smallest submatrix required to be removed such that sum of the remaining matrix is divisible by K

• Last Updated : 18 May, 2021

Given a 2D matrix mat[][] of size N * M and a positive integer K, the task is to find the area of the smallest rectangular submatrix that is required to be removed such that the sum of the remaining elements in the matrix is divisible by K.

Examples:

Input: mat[][] = { {6, 2, 6}, {3, 2, 8}, {2, 5, 3} }, K = 3
Output:
Explanation:
Remove the sub-matrix { mat, mat } from the given matrix.
Since the sum of the remaining matrix is equal to 30 which is divisible by K(=3). Therefore, the required output is 1 * 2 = 2.

Input: mat[][] = { {16, 2, 6, 13}, {33, 21, 8, 8}, {31, 5, 3, 11} }, K = 15
Output: 3

Approach: Follow the steps given below to solve the problem:

• Initialize a variable, say S to store the sum of all elements of the given matrix.
• Initialize a variable, say min_area to store the smallest area that needs to be removed such that the sum of the remaining matrix elements is divisible by K.
• Initialize two variables, say left and right to store the leftmost column and rightmost column of each submatrix respectively.
• Initialize an array, say PrefixRowSum[N], where PrefixRowSum[i] stores the sum of all the elements of the submatrix whose top-most left element is (0, left) and bottom-most right element is (i, right) over all possible values of left and right.
• Iterate over all possible values of left and right and find the length of the smallest subarray needs to be deleted to make the sum of the remaining elements of PrefixRowSum[] equal to (S % K) and update min_area
• Finally, print the value of min_area.

Below is the implementation of the above approach:

C++

 // C++ program to implement // the above approach   #include using namespace std;   // Function to find the length of the // smallest subarray to be removed such // that sum of elements is equal to S % K int removeSmallestSubarray(int arr[], int S,                               int n, int k) {           // Remainder when total_sum     // is divided by K     int target_remainder         = S % k;                         // Stores curr_remainder and the     // most recent index at which     // curr_remainder has occured     unordered_map map1;     map1 = -1;        int curr_remainder = 0;        // Stores required answer     int res = INT_MAX;        for (int i = 0; i < n; i++) {            // Add current element to         // curr_sum and take mod         curr_remainder = (curr_remainder                           + arr[i] + k)                          % k;            // Update current         // remainder index         map1[curr_remainder] = i;            int mod             = (curr_remainder                - target_remainder                + k)               % k;            // If mod already exists in map         // the subarray exists         if (map1.find(mod) !=                         map1.end()) {                                         // Update res             res = min(res, i - map1[mod]);         }     }        // If not possible     if (res == INT_MAX || res == n) {         res = -1;     }        // Return the result     return res; }   // Function to find the smallest submatrix // rqured to be deleted to make the sum // of the matrix divisible by K int smstSubmatDeleted(vector > &mat,                         int N, int M, int K) {       // Stores the sum of     // element of the matrix     int S = 0;       // Traverse the matrix mat[][]     for (int i = 0; i < N; i++) {         for (int j = 0; j < M; j++)           // Update S         S += mat[i][j];     }           // Stores smallest area need to be     // deleted to get sum divisible by K     int min_area = N * M;           // Stores leftmost column     // of each matrix     int left = 0;           // Stores rightmost column     // of each matrix     int right = 0;                 // Stores number of coulmns     // deleted of a matrix     int width;       // Store area of the deleted matrix     int area;       // prefixRowSum[i]: Store sum of sub matrix     // whose topmost left and bottommost right     // position is (0, left) (i, right)     int prefixRowSum[N];             // Iterate over all possible values     // of (left, right)     for (left = 0; left < M; left++) {                   // Initialize all possible values         // of prefixRowSum[] to 0         memset(prefixRowSum, 0,                    sizeof(prefixRowSum));           for (right = left; right < M; right++) {                           // Traverse each row from             // left to right column             for (int i = 0; i < N; i++) {                                   // Update row_sum[i];                 prefixRowSum[i]                       += mat[i][right];                               }                                         // Update width             width = removeSmallestSubarray(                      prefixRowSum, S, N, K);                                                                                 // If no submatrix of the length             // (right  - left + 1) found to get             // the required output             if (width != -1) {                                                     // Update area                 area = (right - left + 1)                                   * (width);                                                     // If area is less than min_area                 if (area < min_area) {                                           // Update min_area                     min_area = area;                 }             }         }     }     return min_area;       }   // Driver Code   int main() {       vector > mat                         = { { 6, 2, 6 },                             { 3, 2, 8 },                             { 2, 5, 3 } };                                   int K = 3;           // Stores number of rows     // in the matrix     int N = mat.size();                 // Stores number of column     // in the matrix     int M = mat.size();          cout<< smstSubmatDeleted(mat, N, M, K);     return 0; }

Java

 // Java program to implement // the above approach import java.util.*; class GFG{   // Function to find the length of the // smallest subarray to be removed such // that sum of elements is equal to S % K static int removeSmallestSubarray(int arr[], int S,                                   int n, int k) {      // Remainder when total_sum   // is divided by K   int target_remainder = S % k;     // Stores curr_remainder and the   // most recent index at which   // curr_remainder has occured   HashMap map1 =           new HashMap<>();     map1.put(0, -1);   int curr_remainder = 0;     // Stores required answer   int res = Integer.MAX_VALUE;     for (int i = 0; i < n; i++)   {     // Add current element to     // curr_sum and take mod     curr_remainder = (curr_remainder +                       arr[i] + k) % k;       // Update current     // remainder index     map1.put(curr_remainder, i);       int mod = (curr_remainder -                target_remainder +                k) % k;       // If mod already exists in map     // the subarray exists     if (map1.containsKey(mod))     {       // Update res       res = Math.min(res, i -                      map1.get(mod));     }   }     // If not possible   if (res == Integer.MAX_VALUE ||       res == n)   {     res = -1;   }     // Return the result   return res; }   // Function to find the smallest submatrix // rqured to be deleted to make the sum // of the matrix divisible by K static int smstSubmatDeleted(int[][]mat,                              int N, int M,                              int K) {   // Stores the sum of   // element of the matrix   int S = 0;     // Traverse the matrix mat[][]   for (int i = 0; i < N; i++)   {     for (int j = 0; j < M; j++)         // Update S       S += mat[i][j];   }     // Stores smallest area need   // to be deleted to get sum   // divisible by K   int min_area = N * M;     // Stores leftmost column   // of each matrix   int left = 0;     // Stores rightmost column   // of each matrix   int right = 0;     // Stores number of coulmns   // deleted of a matrix   int width;     // Store area of the deleted   // matrix   int area;     // prefixRowSum[i]: Store sum   // of sub matrix whose topmost   // left and bottommost right   // position is (0, left) (i, right)   int []prefixRowSum = new int[N];     // Iterate over all possible   // values of (left, right)   for (left = 0; left < M; left++)   {     // Initialize all possible     // values of prefixRowSum[]     // to 0     Arrays.fill(prefixRowSum, 0);       for (right = left;          right < M; right++)     {       // Traverse each row from       // left to right column       for (int i = 0; i < N; i++)       {         // Update row_sum[i];         prefixRowSum[i] +=         mat[i][right];       }         // Update width       width = removeSmallestSubarray(               prefixRowSum, S, N, K);         // If no submatrix of the       // length (right  - left + 1)       // found to get the required       // output       if (width != -1)       {         // Update area         area = (right - left + 1) *                (width);           // If area is less than         // min_area         if (area < min_area)         {           // Update min_area           min_area = area;         }       }     }   }   return min_area; }   // Driver Code   public static void main(String[] args) {   int[][] mat = {{6, 2, 6},                  {3, 2, 8},                  {2, 5, 3}};     int K = 3;     // Stores number of rows   // in the matrix   int N = mat.length;     // Stores number of column   // in the matrix   int M = mat.length;     System.out.print(   smstSubmatDeleted(mat, N,                     M, K)); } }   // This code is contributed by Rajput-Ji

Python3

 # Python3 program to implement # the above approach import sys   # Function to find the length of the # smallest subarray to be removed such # that sum of elements is equal to S % K def removeSmallestSubarray(arr, S, n, k):           # Remainder when total_sum     # is divided by K     target_remainder = S % k           # Stores curr_remainder and the     # most recent index at which     # curr_remainder has occured     map1 = {}     map1 = -1       curr_remainder = 0       # Stores required answer     res = sys.maxsize       for i in range(n):                   # Add current element to         # curr_sum and take mod         curr_remainder = (curr_remainder +                           arr[i] + k) % k                                     # Update current         # remainder index         map1[curr_remainder] = i           mod = (curr_remainder -              target_remainder + k) % k                        # If mod already exists in map         # the subarray exists         if (mod in map1):                           # Update res             res = min(res, i - map1[mod])                   # If not possible     if (res == sys.maxsize or res == n):         res = -1               # Return the result     return res       # Function to find the smallest submatrix # rqured to be deleted to make the sum # of the matrix divisible by K def smstSubmatDeleted(mat, N, M, K):           # Stores the sum of     # element of the matrix     S = 0           # Traverse the matrix mat[][]     for i in range(N):         for j in range(M):           # Update S             S += mat[i][j]       # Stores smallest area need to be     # deleted to get sum divisible by K     min_area = N * M       # Stores leftmost column     # of each matrix     left = 0       # Stores rightmost column     # of each matrix     right = 0           # Stores number of coulmns     # deleted of a matrix     width = 0           # Store area of the deleted matrix     area = 0           # prefixRowSum[i]: Store sum of sub matrix     # whose topmost left and bottommost right     # position is (0, left) (i, right)     prefixRowSm =  * N           # Iterate over all possible values     # of (left, right)     for left in range(M):                   # Initialize all possible values         # of prefixRowSum[] to 0         prefixRowSum =  * N                   for right in range(left, M):                           # Traverse each row from             # left to right column             for i in range(N):                                   # Update row_sum[i]                 prefixRowSum[i] += mat[i][right]                               # Update width             width = removeSmallestSubarray(                 prefixRowSum, S, N, K)                               # If no submatrix of the length             # (right  - left + 1) found to get             # the required output             if (width != -1):                                   # Update area                 area = (right - left + 1) * (width)                                   # If area is less than min_area                 if (area < min_area):                                           # Update min_area                     min_area = area                           return min_area   # Driver Code if __name__ == '__main__':           mat = [ [ 6, 2, 6 ],             [ 3, 2, 8 ],             [ 2, 5, 3 ] ]       K = 3       # Stores number of rows     # in the matrix     N = len(mat)           # Stores number of column     # in the matrix     M = len(mat)           print(smstSubmatDeleted(mat, N, M, K))   # This code is contributed by mohit kumar 29

C#

 // C# program to implement // the above approach using System; using System.Collections.Generic;   class GFG{   // Function to find the length of the // smallest subarray to be removed such // that sum of elements is equal to S % K static int removeSmallestSubarray(int []arr, int S,                                   int n, int k) {       // Remainder when total_sum   // is divided by K   int target_remainder = S % k;     // Stores curr_remainder and the   // most recent index at which   // curr_remainder has occured   Dictionary map1 = new Dictionary();       map1.Add(0, -1);   int curr_remainder = 0;     // Stores required answer   int res = int.MaxValue;     for(int i = 0; i < n; i++)   {           // Add current element to     // curr_sum and take mod     curr_remainder = (curr_remainder +                       arr[i] + k) % k;       // Update current     // remainder index     map1[curr_remainder]=  i;       int mod = (curr_remainder -                target_remainder +                k) % k;       // If mod already exists in map     // the subarray exists     if (map1.ContainsKey(mod))     {               // Update res       res = Math.Min(res, i -                      map1[mod]);     }   }     // If not possible   if (res == int.MaxValue ||       res == n)   {     res = -1;   }     // Return the result   return res; }   // Function to find the smallest submatrix // rqured to be deleted to make the sum // of the matrix divisible by K static int smstSubmatDeleted(int[,]mat,                              int N, int M,                              int K) {       // Stores the sum of   // element of the matrix   int S = 0;     // Traverse the matrix [,]mat   for(int i = 0; i < N; i++)   {     for(int j = 0; j < M; j++)         // Update S       S += mat[i,j];   }     // Stores smallest area need   // to be deleted to get sum   // divisible by K   int min_area = N * M;     // Stores leftmost column   // of each matrix   int left = 0;     // Stores rightmost column   // of each matrix   int right = 0;     // Stores number of coulmns   // deleted of a matrix   int width;     // Store area of the deleted   // matrix   int area;     // prefixRowSum[i]: Store sum   // of sub matrix whose topmost   // left and bottommost right   // position is (0, left) (i, right)   int []prefixRowSum = new int[N];     // Iterate over all possible   // values of (left, right)   for(left = 0; left < M; left++)   {           // Initialize all possible     // values of prefixRowSum[]     // to 0     for(int i = 0; i < prefixRowSum.Length; i++)       prefixRowSum[i] = 0;       for(right = left;         right < M; right++)     {               // Traverse each row from       // left to right column       for(int i = 0; i < N; i++)       {                   // Update row_sum[i];         prefixRowSum[i] += mat[i, right];       }         // Update width       width = removeSmallestSubarray(               prefixRowSum, S, N, K);         // If no submatrix of the       // length (right  - left + 1)       // found to get the required       // output       if (width != -1)       {                   // Update area         area = (right - left + 1) *                (width);           // If area is less than         // min_area         if (area < min_area)         {                       // Update min_area           min_area = area;         }       }     }   }   return min_area; }   // Driver Code   public static void Main(String[] args) {   int[,] mat = { { 6, 2, 6 },                  { 3, 2, 8 },                  { 2, 5, 3 } };     int K = 3;     // Stores number of rows   // in the matrix   int N = mat.GetLength(0);     // Stores number of column   // in the matrix   int M = mat.GetLength(1);   Console.Write(   smstSubmatDeleted(mat, N,                     M, K)); } }   // This code is contributed by shikhasingrajput

Javascript



Output:

2

Time Complexity: O(M2*N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up
Recommended Articles
Page :