Open In App

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

Last Updated : 31 Aug, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

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[1][1], mat[2][1] } 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 <bits/stdc++.h>
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 occurred
    unordered_map<int, int> map1;
    map1[0] = -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<vector<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 columns
    // 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<vector<int> > 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[0].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 occurred
  HashMap<Integer,
          Integer> 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 columns
  // 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[0].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 occurred
    map1 = {}
    map1[0] = -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 columns
    # 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 = [0] * N
     
    # Iterate over all possible values
    # of (left, right)
    for left in range(M):
         
        # Initialize all possible values
        # of prefixRowSum[] to 0
        prefixRowSum = [0] * 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[0])
     
    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 occurred
  Dictionary<int,
             int> map1 = new Dictionary<int,
                                        int>();
   
  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 columns
  // 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




<script>
 
 
// Javascript program to implement
// the above approach
 
// Function to find the length of the
// smallest subarray to be removed such
// that sum of elements is equal to S % K
function removeSmallestSubarray(arr, S, n, k)
{
     
    // Remainder when total_sum
    // is divided by K
    var target_remainder
        = S % k;
         
         
    // Stores curr_remainder and the
    // most recent index at which
    // curr_remainder has occurred
    var map1 = new Map();
    map1.set(0, -1);
  
    var curr_remainder = 0;
  
    // Stores required answer
    var res = 1000000000;
  
    for (var 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.set(curr_remainder, i);
  
        var mod
            = (curr_remainder
               - target_remainder
               + k)
              % k;
  
        // If mod already exists in map
        // the subarray exists
        if (map1.has(mod)) {
             
             
            // Update res
            res = Math.min(res, i - map1.get(mod));
        }
    }
  
    // If not possible
    if (res == 1000000000 || 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
function smstSubmatDeleted(mat, N, M, K)
{
 
    // Stores the sum of
    // element of the matrix
    var S = 0;
 
    // Traverse the matrix mat[][]
    for (var i = 0; i < N; i++) {
        for (var j = 0; j < M; j++)
 
        // Update S
        S += mat[i][j];
    }
     
    // Stores smallest area need to be
    // deleted to get sum divisible by K
    var min_area = N * M;
     
    // Stores leftmost column
    // of each matrix
    var left = 0;
     
    // Stores rightmost column
    // of each matrix
    var right = 0;
     
     
    // Stores number of columns
    // deleted of a matrix
    var width;
 
    // Store area of the deleted matrix
    var area;
 
    // prefixRowSum[i]: Store sum of sub matrix
    // whose topmost left and bottommost right
    // position is (0, left) (i, right)
    var prefixRowSum = Array(N);
 
     
    // Iterate over all possible values
    // of (left, right)
    for (left = 0; left < M; left++) {
         
        // Initialize all possible values
        // of prefixRowSum[] to 0
        prefixRowSum = Array(N).fill(0);
 
        for (right = left; right < M; right++) {
             
            // Traverse each row from
            // left to right column
            for (var 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  
var mat  = [ [ 6, 2, 6 ],
             [ 3, 2, 8 ],
             [ 2, 5, 3 ] ];
                         
var K = 3;
 
// Stores number of rows
// in the matrix
var N = mat.length;
 
 
// Stores number of column
// in the matrix
var M = mat[0].length;
 
document.write( smstSubmatDeleted(mat, N, M, K));
 
</script>


Output: 

2

 

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



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads