Open In App

Minimize rows to be made zero for last column sum to be at most any one column

Improve
Improve
Like Article
Like
Save
Share
Report

Given an N * M matrix mat[][] consisting of non-negative integers. In one operation, select any row and change all elements to 0. The task is to find the minimum number of operations required such that the sum of elements in the Mth column is less than or equal to the sum of elements in jth column for at least one ‘j’ ( where 1 ≤ ‘j’ ≤ ‘M’-1).

Examples:

Input: N = 3, M = 3, mat[][] = [ [3, 1, 2], [2, 3, 5], [3, 1, 2] ]
Output: 1
Explanation: Initially, sum of elements in each columns, S = [8, 5, 9].
If we operate on the second row, the updated array of sums S = [6, 2, 4], where S[3] < S[1]. 
Hence we need at least one operation.

Input: N = 3, M=3, MAT[][] = [[3, 2, 6], [ 1, 2, 3 ], [5, 1, 9] ]
Output: 3
Explanation: The only possible way is to make all the elements in the matrix as 0. 
i.e, perform one operation on each row. After these operations S[0] = S[1] = S[2].
Return 3 as final answer.

 

Naive approach: The simplest approach is to try all possible combinations of rows and make them and check for each combination if the condition is satisfied or not.

  • Operate on some number of rows, and the simplest way is to try with all possible combinations of rows.
  • There are ‘N‘ rows in the matrix, so there will be a total of (2 ^ N) ways for the selection of rows to be operated.
  • Generate all the possible combinations and for each of them, do the following:
  • Create a copy ‘tmp‘ of the original matrix mat[][].
  • Count the number of rows in each combination and mark all the elements in corresponding rows as 0 (in ‘tmp‘ only).
  • Find the sum of elements in the Mth column, let it be ‘sumM’.
  • Compute the sum in each column (from 1 to ‘M-1’), and if the sum of any of these columns is greater or equal to the Mth column, consider the number of rows as one of the answers.
  • Among all the combinations, return the smallest size (minimum number of rows) for which we found at least one column having a sum greater or equal to the Mth column.

Below is the implementation of the above approach :

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
int countMinOp(int n, int m, vector<vector<int> >& mat)
{
    // If all rows are operated, there
    // will be definitely an answer.
    int ans = n;
 
    // Choose all possible combinations of rows.
    for (int i = 0; i < (1 << n); i++) {
 
        // Copying 'mat' to 'tmp'.
        vector<vector<int> > tmp = mat;
 
        // Variable to store the
        // count of rows cleared.
        int cnt = 0;
 
        for (int j = 0; j < n; j++) {
 
            // Check if current row
            // is set in combination.
            if (((i >> j) & 1) == 1) {
 
                // Clear the 'j-th' row.
                cnt++;
                for (int k = 0; k < m; k++) {
                    tmp[j][k] = 0;
                }
            }
        }
 
        int sumM = 0;
        bool flag = false;
 
        // Sum of the 'Mth' column.
        for (int j = 0; j < n; j++) {
            sumM += tmp[j][m - 1];
        }
 
        // Check if there exists
        // some '1' <= 'j' <= 'M-1'
        // such that Sum[j] >= Sum[M].
        for (int j = 0; j < m - 1; j++) {
 
            int sum = 0;
 
            // Calculating the sum
            // of 'jth' column.
            for (int k = 0; k < n; k++) {
                sum += tmp[k][j];
            }
 
            // Check if current column has
            // sum greater than 'Mth' column.
            if (sum >= sumM) {
                flag = true;
                break;
            }
        }
 
        // If condition is satisfied,
        // then check if this is the
        // minimum number of operations.
        if (flag == true) {
            ans = min(ans, cnt);
        }
    }
 
    // Return the final result.
    return ans;
}
 
// Driver Code
int main()
{
    int N = 3;
    int M = 3;
    vector<vector<int> > mat
        = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    cout << countMinOp(N, M, mat);
    return 0;
}


Java




// Java code to implement the approach
import java.util.*;
public class GFG {
 
  static int countMinOp(int n, int m, int mat[][])
  {
     
    // If all rows are operated, there
    // will be definitely an answer.
    int ans = n;
 
    // Choose all possible combinations of rows.
    for (int i = 0; i < (1 << n); i++) {
 
      // Copying 'mat' to 'tmp'.
      int tmp[][] = mat;
 
      // Variable to store the
      // count of rows cleared.
      int cnt = 0;
 
      for (int j = 0; j < n; j++) {
 
        // Check if current row
        // is set in combination.
        if (((i >> j) & 1) == 1) {
 
          // Clear the 'j-th' row.
          cnt++;
          for (int k = 0; k < m; k++) {
            tmp[j][k] = 0;
          }
        }
      }
 
      int sumM = 0;
      boolean flag = false;
 
      // Sum of the 'Mth' column.
      for (int j = 0; j < n; j++) {
        sumM += tmp[j][m - 1];
      }
 
      // Check if there exists
      // some '1' <= 'j' <= 'M-1'
      // such that Sum[j] >= Sum[M].
      for (int j = 0; j < m - 1; j++) {
 
        int sum = 0;
 
        // Calculating the sum
        // of 'jth' column.
        for (int k = 0; k < n; k++) {
          sum += tmp[k][j];
        }
 
        // Check if current column has
        // sum greater than 'Mth' column.
        if (sum >= sumM) {
          flag = true;
          break;
        }
      }
 
      // If condition is satisfied,
      // then check if this is the
      // minimum number of operations.
      if (flag == true) {
        ans = Math.min(ans, cnt);
      }
    }
 
    // Return the final result.
    return ans;
  }
 
  // Driver Code
  public static void main(String args[])
  {
    int N = 3;
    int M = 3;
    int mat[][]
      = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    System.out.print(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Python3




# Python program for the above approach
def countMinOp(n, m, mat) :
     
    # If all rows are operated, there
    # will be definitely an answer.
    ans = n
 
    # Choose all possible combinations of rows.
    for i in range(0, (1 << n)):
 
        # Copying 'mat' to 'tmp'.
        tmp = mat
 
        # Variable to store the
        # count of rows cleared.
        cnt = 0
 
        for j in range(0, n):
 
            # Check if current row
            # is set in combination.
            if (((i >> j) & 1) == 1) :
 
                # Clear the 'j-th' row.
                cnt += 1
                for j in range(0, m):
                    tmp[j][k] = 0
                 
        sumM = 0
        flag = False
 
        # Sum of the 'Mth' column.
        for j in range(0, n):
            sumM += tmp[j][m - 1]
         
        # Check if there exists
        # some '1' <= 'j' <= 'M-1'
        # such that Sum[j] >= Sum[M].
        for j in range(0, m-1): 
 
            sum = 0
 
            # Calculating the sum
            # of 'jth' column.
            for k in range(0, n):
                sum += tmp[k][j]
             
            # Check if current column has
            # sum greater than 'Mth' column.
            if (sum >= sumM) :
                flag = True
                break
             
        # If condition is satisfied,
        # then check if this is the
        # minimum number of operations.
        if (flag == True) :
            ans = min(ans, cnt)
         
    # Return the final result.
    return ans
 
# Driver Code
N = 3
M = 3
mat = [[3, 1, 2 ], [ 2, 3, 5 ], [ 3, 1, 2 ]]
print(countMinOp(N, M, mat))
 
# This code is contributed by code_hunt.


C#




// C# code to implement the approach
using System;
class GFG {
 
  static int countMinOp(int n, int m, int [,]mat)
  {
     
    // If all rows are operated, there
    // will be definitely an answer.
    int ans = n;
 
    // Choose all possible combinations of rows.
    for (int i = 0; i < (1 << n); i++) {
 
      // Copying 'mat' to 'tmp'.
      int [,]tmp = mat;
 
      // Variable to store the
      // count of rows cleared.
      int cnt = 0;
 
      for (int j = 0; j < n; j++) {
 
        // Check if current row
        // is set in combination.
        if (((i >> j) & 1) == 1) {
 
          // Clear the 'j-th' row.
          cnt++;
          for (int k = 0; k < m; k++) {
            tmp[j,k] = 0;
          }
        }
      }
 
      int sumM = 0;
      bool flag = false;
 
      // Sum of the 'Mth' column.
      for (int j = 0; j < n; j++) {
        sumM += tmp[j,m - 1];
      }
 
      // Check if there exists
      // some '1' <= 'j' <= 'M-1'
      // such that Sum[j] >= Sum[M].
      for (int j = 0; j < m - 1; j++) {
 
        int sum = 0;
 
        // Calculating the sum
        // of 'jth' column.
        for (int k = 0; k < n; k++) {
          sum += tmp[k,j];
        }
 
        // Check if current column has
        // sum greater than 'Mth' column.
        if (sum >= sumM) {
          flag = true;
          break;
        }
      }
 
      // If condition is satisfied,
      // then check if this is the
      // minimum number of operations.
      if (flag == true) {
        ans = Math.Min(ans, cnt);
      }
    }
 
    // Return the final result.
    return ans;
  }
 
  // Driver Code
  public static void Main()
  {
    int N = 3;
    int M = 3;
    int [,]mat
      = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    Console.Write(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript




<script>
       // JavaScript code for the above approach
 
 
       function countMinOp(n, m, mat) {
           // If all rows are operated, there
           // will be definitely an answer.
           let ans = n;
 
           // Choose all possible combinations of rows.
           for (let i = 0; i < (1 << n); i++) {
 
               // Copying 'mat' to 'tmp'.
               let tmp = [...mat];
 
               // Variable to store the
               // count of rows cleared.
               let cnt = 0;
 
               for (let j = 0; j < n; j++) {
 
                   // Check if current row
                   // is set in combination.
                   if (((i >> j) & 1) == 1) {
 
                       // Clear the 'j-th' row.
                       cnt++;
                       for (let k = 0; k < m; k++) {
                           tmp[j][k] = 0;
                       }
                   }
               }
 
               let sumM = 0;
               let flag = false;
 
               // Sum of the 'Mth' column.
               for (let j = 0; j < n; j++) {
                   sumM += tmp[j][m - 1];
               }
 
               // Check if there exists
               // some '1' <= 'j' <= 'M-1'
               // such that Sum[j] >= Sum[M].
               for (let j = 0; j < m - 1; j++) {
 
                   let sum = 0;
 
                   // Calculating the sum
                   // of 'jth' column.
                   for (let k = 0; k < n; k++) {
                       sum += tmp[k][j];
                   }
 
                   // Check if current column has
                   // sum greater than 'Mth' column.
                   if (sum >= sumM) {
                       flag = true;
                       break;
                   }
               }
 
               // If condition is satisfied,
               // then check if this is the
               // minimum number of operations.
               if (flag == true) {
                   ans = Math.min(ans, cnt);
               }
           }
 
           // Return the final result.
           return ans;
       }
 
       // Driver Code
 
       let N = 3;
       let M = 3;
       let mat
           = [[3, 1, 2], [2, 3, 5], [3, 1, 2]];
       document.write(countMinOp(N, M, mat));
 
    // This code is contributed by Potta Lokesh
   </script>


 
 

Output

1

 

Time Complexity: O((2N) * N * M)
Auxiliary Space: O(N * M)

 

Efficient Approach: The basic idea of the efficient approach is based on the concept that we need at least one column for which the sum of elements is not smaller than the final column. So, solve the problem for a fixed column and repeat each column. Follow the steps mentioned below to solve the problem:

 

  • Consider two arrays, ‘A1’ and ‘A2’, both of length ‘N’ where the array ‘A1’ denotes any column among 1 to ‘M’-1 and the array ‘A2’ denotes the Mth column.
  • We erase some indices from both arrays such that the sum of remaining elements in ‘A1’ is not smaller than ‘A2’, i.e., Sum(A1) >= Sum(A2).
    • For the deletion part, it is optimal to delete such an index for which (‘A1[i]’ – ‘A2[i]’) is more negative among all the indices.
    • If (‘A1[i]’ – ‘A2[i]’) is non-negative, we don’t need to delete this index at all.
    • Take the most negative one because we may or may not delete an index where (‘A1[i]’ – ‘A2[i]’) is negative. Taking an example if A1 = [3, 1, 4] and A2 = [2, 3, 2]. Here, (A1[2] – A2[2]) is negative but we don’t delete this because other elements are taking care of the total sum.
  • To perform the above task optimally:
    • create an array ‘diff’ that contains all the corresponding elements’ differences, i.e., ‘A1[i]’ – ‘A2[i]’.
    • Sort the array ‘diff’ in decreasing order of elements.
    • Take the longest prefix until the prefix-sum is non-negative and the rest of the elements need to be deleted.
  • Repeat the above process for each column and consider the minimum number of elements that need to be deleted.

 

Below is the implementation of the above approach.

 

C++




// C++ code to implement the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
int countMinOp(int n, int m,
               vector<vector<int> >& mat)
{
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
        // Calculate difference of
        // elements in i-th column
        // with final column.
        vector<int> diff;
        for (int j = 0; j < n; j++) {
            diff.push_back(mat[j][i]
                           - mat[j][m - 1]);
        }
 
        // Sort differences in
        // non-decreasing order.
        sort(diff.begin(), diff.end(),
             greater<int>());
     
 
        // Consider differences
        // until sum of differences is
        // non-negative, i.e.,
        // Sum[i] >= Sum[M].
        int sum = 0, k = 0;
 
        while ((k < n) and (sum + diff[k]
                            >= 0)) {
            sum += diff[k];
            k++;
        }
 
        // Remaining elements must
        // be removed. Minimize the answer
        ans = min(ans, n - k);
    }
    return ans;
}
 
// Driver Code
int main()
{
    int N = 3;
    int M = 3;
    vector<vector<int> > mat
        = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    cout << countMinOp(N, M, mat);
    return 0;
}


Java




// JAVA code to implement the above approach
import java.util.*;
class GFG {
  public static int
    countMinOp(int n, int m,
               ArrayList<ArrayList<Integer> > mat)
  {
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
      // Calculate difference of
      // elements in i-th column
      // with final column.
      ArrayList<Integer> diff
        = new ArrayList<Integer>();
      for (int j = 0; j < n; j++) {
        diff.add(mat.get(j).get(i)
                 - mat.get(j).get(m - 1));
      }
 
      // Sort differences in
      // non-decreasing order.
      Collections.sort(diff,
                       Collections.reverseOrder());
 
      // Consider differences
      // until sum of differences is
      // non-negative, i.e.,
      // Sum[i] >= Sum[M].
      int sum = 0, k = 0;
 
      while ((k < n) && (sum + diff.get(k) >= 0)) {
        sum += diff.get(k);
        k++;
      }
 
      // Remaining elements must
      // be removed. Minimize the answer
      ans = Math.min(ans, n - k);
    }
    return ans;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int N = 3;
    int M = 3;
    ArrayList<ArrayList<Integer> > mat
      = new ArrayList<ArrayList<Integer> >();
    ArrayList<Integer> temp1 = new ArrayList<Integer>(
      Arrays.asList(3, 1, 2));
    ArrayList<Integer> temp2 = new ArrayList<Integer>(
      Arrays.asList(2, 3, 5));
    ArrayList<Integer> temp3 = new ArrayList<Integer>(
      Arrays.asList(3, 1, 2));
    mat.add(temp1);
    mat.add(temp2);
    mat.add(temp3);
    System.out.print(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by Taranpreet


Python3




# Python 3 code to implement the above approach
def countMinOp(n, m, mat):
 
    # If all rows are operated,
    # there will be definitely an
    # answer.
    ans = n
 
    # Choose each column one by one.
    for i in range(m - 1):
 
        # Calculate difference of
        # elements in i-th column
        # with final column.
        diff = []
        for j in range(n):
            diff.append(mat[j][i]
                        - mat[j][m - 1])
 
        # Sort differences in
        # non-decreasing order.
        diff.sort(reverse = True)
 
        # Consider differences
        # until sum of differences is
        # non-negative, i.e.,
        # Sum[i] >= Sum[M].
        sum = 0
        k = 0
 
        while ((k < n) and (sum + diff[k]
                            >= 0)):
            sum += diff[k]
            k += 1
 
        # Remaining elements must
        # be removed. Minimize the answer
        ans = min(ans, n - k)
 
    return ans
 
# Driver Code
if __name__ == "__main__":
 
    N = 3
    M = 3
    mat = [[3, 1, 2], [2, 3, 5], [3, 1, 2]]
    print(countMinOp(N, M, mat))
 
    # This code is contributed by ukasp.


C#




// C# program of the above approach
using System;
using System.Linq;
using System.Collections.Generic;
 
class GFG
{
 
  static int
    countMinOp(int n, int m,
               List<List<int> > mat)
  {
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
      // Calculate difference of
      // elements in i-th column
      // with final column.
      List<int> diff
        = new List<int>();
 
 
      diff.Add(-3);
      diff.Add(1);
      diff.Add(-1);
      diff.Add(-2);
      diff.Add(-1);
 
      // Sort differences in
      // non-decreasing order.
      diff.Sort();
      diff.Reverse();
 
      // Consider differences
      // until sum of differences is
      // non-negative, i.e.,
      // Sum[i] >= Sum[M].
      int sum = 0, k = 0;
 
      while ((k < n) && (sum + diff[k] >= 0)) {
        sum += diff[k];
        k++;
      }
 
      // Remaining elements must
      // be removed. Minimize the answer
      ans = Math.Min(ans, n - k);
    }
    return ans;
  }
 
  // Driver Code
  public static void Main()
  {
    int N = 3;
    int M = 3;
    List<List<int> > mat
      = new List<List<int> >();
    List<int> temp1 = new List<int>();
    temp1.Add(3);temp1.Add(1);temp1.Add(2);
    List<int> temp2 = new List<int>();
    temp2.Add(2);temp2.Add(3);temp2.Add(5);
    List<int> temp3 = new List<int>();
    temp3.Add(3);temp3.Add(1);temp3.Add(2);
    mat.Add(temp1);
    mat.Add(temp2);
    mat.Add(temp3);
    Console.Write(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by sanjoy_62.


Javascript




<script>
 
// JavaScript code to implement the above approach
function countMinOp(n, m, mat)
{
 
    // If all rows are operated,
    // there will be definitely an
    // answer.
    let ans = n;
 
    // Choose each column one by one.
    for (let i = 0; i < m - 1; i++) {
 
        // Calculate difference of
        // elements in i-th column
        // with final column.
        let diff = [];
        for (let j = 0; j < n; j++) {
            diff.push(mat[j][i]
                           - mat[j][m - 1]);
        }
 
        // Sort differences in
        // non-decreasing order.
        diff.sort((a,b)=>b-a);
 
        // Consider differences
        // until sum of differences is
        // non-negative, i.e.,
        // Sum[i] >= Sum[M].
        let sum = 0, k = 0;
 
        while ((k < n) && (sum + diff[k] >= 0)) {
            sum += diff[k];
            k++;
        }
 
        // Remaining elements must
        // be removed. Minimize the answer
        ans = Math.min(ans, n - k);
    }
    return ans;
}
 
// Driver Code
 
let N = 3;
let M = 3;
let mat = [ [ 3, 1, 2 ],[ 2, 3, 5 ],[ 3, 1, 2] ];
document.write(countMinOp(N, M, mat));
 
// This code is contributed by shinjanpatra
 
</script>


 
 

Output

1

 

Time Complexity: O(N * M * logN)
Auxiliary Space: O(N)

 



Last Updated : 05 Apr, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads