Binary Matrix after flipping submatrices in given range for Q queries
Given a binary matrix arr[][] of dimensions M x N and Q queries of the form (x1, y1, x2, y2), where (x1, y1) and (x2, y2) denotes the top-left and bottom-right indices of the submatrix required to be flipped(convert 0s to 1s and vice versa) respectively. The task is to print the final matrix obtained after performing the given Q queries.
Examples:
Input: arr[][] = {{0, 1, 0}, {1, 1, 0}}, queries[][] = {{1, 1, 2, 3}}
Output: [[1, 0, 1], [0, 0, 1]]
Explanation:
The submatrix to be flipped is equal to {{0, 1, 0}, {1, 1, 0}}
The flipped matrix is {{1, 0, 1}, {0, 0, 1}}.Input: arr[][] = {{0, 1, 0}, {1, 1, 0}}, queries[][] = {{1, 1, 2, 3}, {1, 1, 1, 1], {1, 2, 2, 3}}
Output: [[0, 1, 0], [0, 1, 0]]
Explanation:
Query 1:
Submatrix to be flipped = [[0, 1, 0], [1, 1, 0]]
Flipped submatrix is [[1, 0, 1], [0, 0, 1]].
Therefore, the modified matrix is [[1, 0, 1], [0, 0, 1]].
Query 2:
Submatrix to be flipped = [[1]]
Flipped submatrix is [[0]]
Therefore, the matrix is [[0, 0, 1], [0, 0, 1]].
Query 3:
Submatrix to be flipped = [[0, 1], [0, 1]]
Flipped submatrix is [[1, 0], [1, 0]]
Therefore, the modified matrix is [[0, 1, 0], [0, 1, 0]].
Naive Approach: The simplest approach to solve the problem for each query is to iterate over the given submatrices and for every element, check if it is 0 or 1, and flip accordingly. After completing these operations for all the queries, print the final matrix obtained.
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 flip a submatrices void manipulation(vector<vector< int >> &matrix, vector< int > &q) { // Boundaries of the submatrix int x1 = q[0], y1 = q[1], x2 = q[2], y2 = q[3]; // Iterate over the submatrix for ( int i = x1 - 1; i < x2; i++) { for ( int j = y1 - 1; j < y2; j++) { // Check for 1 or 0 // and flip accordingly if (matrix[i][j] == 1) matrix[i][j] = 0; else matrix[i][j] = 1; } } } // Function to perform the queries void queries_fxn(vector<vector< int >> &matrix, vector<vector< int >> &queries) { for ( auto q : queries) manipulation(matrix, q); } // Driver code int main() { vector<vector< int >> matrix = { { 0, 1, 0 }, { 1, 1, 0 } }; vector<vector< int >> queries = { { 1, 1, 2, 3 }, { 1, 1, 1, 1 }, { 1, 2, 2, 3 } }; // Function call queries_fxn(matrix, queries); cout << "[" ; for ( int i = 0; i < matrix.size(); i++) { cout << "[" ; for ( int j = 0; j < matrix[i].size(); j++) cout << matrix[i][j] << " " ; if (i == matrix.size() - 1) cout << "]" ; else cout << "], " ; } cout << "]" ; } // This code is contributed by bgangwar59 |
Java
// Java program to implement // the above approach import java.util.*; import java.lang.*; class GFG{ // Function to flip a submatrices static void manipulation( int [][] matrix, int [] q) { // Boundaries of the submatrix int x1 = q[ 0 ], y1 = q[ 1 ], x2 = q[ 2 ], y2 = q[ 3 ]; // Iterate over the submatrix for ( int i = x1 - 1 ; i < x2; i++) { for ( int j = y1 - 1 ; j < y2; j++) { // Check for 1 or 0 // and flip accordingly if (matrix[i][j] == 1 ) matrix[i][j] = 0 ; else matrix[i][j] = 1 ; } } } // Function to perform the queries static void queries_fxn( int [][] matrix, int [][] queries) { for ( int [] q : queries) manipulation(matrix, q); } // Driver code public static void main (String[] args) { int [][] matrix = {{ 0 , 1 , 0 }, { 1 , 1 , 0 }}; int [][] queries = {{ 1 , 1 , 2 , 3 }, { 1 , 1 , 1 , 1 }, { 1 , 2 , 2 , 3 }}; // Function call queries_fxn(matrix, queries); System.out.print( "[" ); for ( int i = 0 ; i < matrix.length; i++) { System.out.print( "[" ); for ( int j = 0 ; j < matrix[i].length; j++) System.out.print(matrix[i][j] + " " ); if (i == matrix.length - 1 ) System.out.print( "]" ); else System.out.print( "], " ); } System.out.print( "]" ); } } // This code is contributed by offbeat |
Python3
# Python3 Program to implement # the above approach # Function to flip a submatrices def manipulation(matrix, q): # Boundaries of the submatrix x1, y1, x2, y2 = q # Iterate over the submatrix for i in range (x1 - 1 , x2): for j in range (y1 - 1 , y2): # Check for 1 or 0 # and flip accordingly if matrix[i][j]: matrix[i][j] = 0 else : matrix[i][j] = 1 # Function to perform the queries def queries_fxn(matrix, queries): for q in queries: manipulation(matrix, q) # Driver Code matrix = [[ 0 , 1 , 0 ], [ 1 , 1 , 0 ]] queries = [[ 1 , 1 , 2 , 3 ], \ [ 1 , 1 , 1 , 1 ], \ [ 1 , 2 , 2 , 3 ]] # Function call queries_fxn(matrix, queries) print (matrix) |
C#
// C# program to implement // the above approach using System; class GFG{ // Function to flip a submatrices static void manipulation( int [,] matrix, int [] q) { // Boundaries of the submatrix int x1 = q[0], y1 = q[1], x2 = q[2], y2 = q[3]; // Iterate over the submatrix for ( int i = x1 - 1; i < x2; i++) { for ( int j = y1 - 1; j < y2; j++) { // Check for 1 or 0 // and flip accordingly if (matrix[i, j] == 1) matrix[i, j] = 0; else matrix[i, j] = 1; } } } public static int [] GetRow( int [,] matrix, int row) { var rowLength = matrix.GetLength(1); var rowVector = new int [rowLength]; for ( var i = 0; i < rowLength; i++) rowVector[i] = matrix[row, i]; return rowVector; } // Function to perform the queries static void queries_fxn( int [,] matrix, int [,] queries) { for ( int i = 0; i < queries.GetLength(0); i++) manipulation(matrix, GetRow(queries, i)); } // Driver code public static void Main(String[] args) { int [,] matrix = { { 0, 1, 0 }, { 1, 1, 0 } }; int [,] queries = { { 1, 1, 2, 3 }, { 1, 1, 1, 1 }, { 1, 2, 2, 3 } }; // Function call queries_fxn(matrix, queries); Console.Write( "[" ); for ( int i = 0; i < matrix.GetLength(0); i++) { Console.Write( "[" ); for ( int j = 0; j < matrix.GetLength(1); j++) Console.Write(matrix[i, j] + ", " ); if (i == matrix.Length - 1) Console.Write( "]" ); else Console.Write( "], " ); } Console.Write( "]" ); } } // This code is contributed by Princi Singh |
Javascript
<script> // Javascript program to implement // the above approach // Function to flip a submatrices function manipulation(matrix, q) { // Boundaries of the submatrix let x1 = q[0], y1 = q[1], x2 = q[2], y2 = q[3]; // Iterate over the submatrix for (let i = x1 - 1; i < x2; i++) { for (let j = y1 - 1; j < y2; j++) { // Check for 1 or 0 // and flip accordingly if (matrix[i][j] == 1) matrix[i][j] = 0; else matrix[i][j] = 1; } } } // Function to perform the queries function queries_fxn(matrix, queries) { for (let q of queries) manipulation(matrix, q); } // Driver code let matrix = [[0, 1, 0], [1, 1, 0]]; let queries = [[1, 1, 2, 3], [1, 1, 1, 1], [1, 2, 2, 3]]; // Function call queries_fxn(matrix, queries); document.write( "[" ); for (let i = 0; i < matrix.length; i++) { document.write( "[" ); for (let j = 0; j < matrix[i].length; j++) { if (j < matrix[i].length - 1) { document.write(matrix[i][j] + ", " ); } else { document.write(matrix[i][j] + " " ); } } if (i == matrix.length - 1) document.write( "]" ); else document.write( "], " ); } document.write( "]" ); // This code is contributed by _saurabh_jaiswal </script> |
[[0, 1, 0], [0, 1, 0]]
Time complexity: O( N * M * Q)
Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized using Dynamic programming and Prefix Sum technique. Mark the boundaries of the submatrices involved in each query and then calculate the prefix sum of the operations involved in the matrix and update the matrix accordingly. Follow the steps below to solve the problem:
- Initialize a 2D state space table dp[][] to store the count of flips at respective indices of the matrix
- For each query {x1, y1, x2, y2, K}, update the dp[][] matrix by the following operations:
- dp[x1][y1] += 1
- dp[x2 + 1][y1] -= 1
- dp[x2 + 1][y2 + 1] += 1
- dp[x1][y2 + 1] -= 1
- Now, traverse over the dp[][] matrix and update dp[i][j] by calculating the prefix sum of the rows and columns and diagonals by the following relation:
dp[i][j] = dp[i][j] + dp[i-1][j] + dp[i][j – 1] – dp[i – 1][j – 1]
- If dp[i][j] is found to be odd, reduce mat[i – 1][j – 1] by 1.
- Finally, print the updated matrix mat[][] as the result.
Below is the implementation of the above approach :
Python3
# Python3 program to implement # the above approach # Function to modify dp[][] array by # generating prefix sum def modifyDP(matrix, dp): for j in range ( 1 , len (matrix) + 1 ): for k in range ( 1 , len (matrix[ 0 ]) + 1 ): # Update the tabular data dp[j][k] = dp[j][k] + dp[j - 1 ][k] \ + dp[j][k - 1 ] - dp[j - 1 ][k - 1 ] # If the count of flips is even if dp[j][k] % 2 ! = 0 : matrix[j - 1 ][k - 1 ] = int (matrix[j - 1 ][k - 1 ]) ^ 1 # Function to update dp[][] matrix # for each query def queries_fxn(matrix, queries, dp): for q in queries: x1, y1, x2, y2 = q # Update the table dp[x1][y1] + = 1 dp[x2 + 1 ][y2 + 1 ] + = 1 dp[x1][y2 + 1 ] - = 1 dp[x2 + 1 ][y1] - = 1 modifyDP(matrix, dp) # Driver Code matrix = [[ 0 , 1 , 0 ], [ 1 , 1 , 0 ]] queries = [[ 1 , 1 , 2 , 3 ], \ [ 1 , 1 , 1 , 1 ], \ [ 1 , 2 , 2 , 3 ]] # Initialize dp table dp = [[ 0 for i in range ( len (matrix[ 0 ]) + 2 )] \ for j in range ( len (matrix) + 2 )] queries_fxn(matrix, queries, dp) print (matrix) |
[[0, 1, 0], [0, 1, 0]]
Time Complexity: O(N * M )
Auxiliary Space: O(N * M)