Binary Matrix after flipping submatrices in given range for Q queries
Last Updated :
08 May, 2023
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++
#include<bits/stdc++.h>
using namespace std;
void manipulation(vector<vector< int >> &matrix,
vector< int > &q)
{
int x1 = q[0], y1 = q[1],
x2 = q[2], y2 = q[3];
for ( int i = x1 - 1; i < x2; i++)
{
for ( int j = y1 - 1; j < y2; j++)
{
if (matrix[i][j] == 1)
matrix[i][j] = 0;
else
matrix[i][j] = 1;
}
}
}
void queries_fxn(vector<vector< int >> &matrix,
vector<vector< int >> &queries)
{
for ( auto q : queries)
manipulation(matrix, q);
}
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 } };
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 << "]" ;
}
|
Java
import java.util.*;
import java.lang.*;
class GFG{
static void manipulation( int [][] matrix,
int [] q)
{
int x1 = q[ 0 ], y1 = q[ 1 ],
x2 = q[ 2 ], y2 = q[ 3 ];
for ( int i = x1 - 1 ; i < x2; i++)
{
for ( int j = y1 - 1 ; j < y2; j++)
{
if (matrix[i][j] == 1 )
matrix[i][j] = 0 ;
else
matrix[i][j] = 1 ;
}
}
}
static void queries_fxn( int [][] matrix,
int [][] queries)
{
for ( int [] q : queries)
manipulation(matrix, q);
}
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 }};
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( "]" );
}
}
|
Python3
def manipulation(matrix, q):
x1, y1, x2, y2 = q
for i in range (x1 - 1 , x2):
for j in range (y1 - 1 , y2):
if matrix[i][j]:
matrix[i][j] = 0
else :
matrix[i][j] = 1
def queries_fxn(matrix, queries):
for q in queries:
manipulation(matrix, q)
matrix = [[ 0 , 1 , 0 ], [ 1 , 1 , 0 ]]
queries = [[ 1 , 1 , 2 , 3 ], \
[ 1 , 1 , 1 , 1 ], \
[ 1 , 2 , 2 , 3 ]]
queries_fxn(matrix, queries)
print (matrix)
|
C#
using System;
class GFG{
static void manipulation( int [,] matrix,
int [] q)
{
int x1 = q[0], y1 = q[1],
x2 = q[2], y2 = q[3];
for ( int i = x1 - 1; i < x2; i++)
{
for ( int j = y1 - 1; j < y2; j++)
{
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;
}
static void queries_fxn( int [,] matrix,
int [,] queries)
{
for ( int i = 0; i < queries.GetLength(0); i++)
manipulation(matrix, GetRow(queries, i));
}
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 } };
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( "]" );
}
}
|
Javascript
<script>
function manipulation(matrix, q) {
let x1 = q[0], y1 = q[1],
x2 = q[2], y2 = q[3];
for (let i = x1 - 1; i < x2; i++) {
for (let j = y1 - 1; j < y2; j++) {
if (matrix[i][j] == 1)
matrix[i][j] = 0;
else
matrix[i][j] = 1;
}
}
}
function queries_fxn(matrix, queries) {
for (let q of queries)
manipulation(matrix, q);
}
let matrix = [[0, 1, 0],
[1, 1, 0]];
let queries = [[1, 1, 2, 3],
[1, 1, 1, 1],
[1, 2, 2, 3]];
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( "]" );
</script>
|
Output:
[[0, 1, 0], [0, 1, 0]]
Time complexity: O( N * M * Q), The time complexity of the given program is O(N*M*Q), where N is the number of queries, M is the number of rows in the matrix, and Q is the number of columns in the matrix. This is because we need to iterate over each element in the submatrix for each query, which takes O(N*M) time, and we have Q queries to perform.
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 :
C++
#include <iostream>
#include <vector>
using namespace std;
void modifyDP(vector<vector< int > >& matrix,
vector<vector< int > >& dp)
{
int row = matrix.size();
int col = matrix[0].size();
for ( int j = 1; j <= row; j++) {
for ( int k = 1; k <= col; k++) {
dp[j][k] = dp[j][k] + dp[j - 1][k]
+ dp[j][k - 1] - dp[j - 1][k - 1];
if (dp[j][k] % 2 != 0) {
matrix[j - 1][k - 1]
= matrix[j - 1][k - 1] ^ 1;
}
}
}
}
void queries_fxn(vector<vector< int > >& matrix,
vector<vector< int > >& queries,
vector<vector< int > >& dp)
{
for ( int i = 0; i < queries.size(); i++) {
int x1 = queries[i][0];
int y1 = queries[i][1];
int x2 = queries[i][2];
int y2 = queries[i][3];
dp[x1][y1] += 1;
dp[x2 + 1][y2 + 1] += 1;
dp[x1][y2 + 1] -= 1;
dp[x2 + 1][y1] -= 1;
}
modifyDP(matrix, dp);
}
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 } };
vector<vector< int > > dp(
matrix.size() + 2,
vector< int >(matrix[0].size() + 2, 0));
queries_fxn(matrix, queries, dp);
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 << "], " ;
}
}
}
|
Java
import java.util.*;
import java.io.*;
class GFG{
static void modifyDP( int matrix[][], int dp[][]){
for ( int j = 1 ; j <= matrix.length ; j++){
for ( int k = 1 ; k <= matrix[ 0 ].length ; k++){
dp[j][k] = dp[j][k] + dp[j- 1 ][k] + dp[j][k- 1 ]- dp[j- 1 ][k- 1 ];
if (dp[j][k] % 2 != 0 ){
matrix[j- 1 ][k- 1 ] = matrix[j- 1 ][k- 1 ] ^ 1 ;
}
}
}
}
static void queries_fxn( int matrix[][], int queries[][], int dp[][]){
for ( int i = 0 ; i < queries.length ; i++){
int x1 = queries[i][ 0 ];
int y1 = queries[i][ 1 ];
int x2 = queries[i][ 2 ];
int y2 = queries[i][ 3 ];
dp[x1][y1] += 1 ;
dp[x2 + 1 ][y2 + 1 ] += 1 ;
dp[x1][y2 + 1 ] -= 1 ;
dp[x2 + 1 ][y1] -= 1 ;
}
modifyDP(matrix, dp);
}
public static void main(String args[])
{
int matrix[][] = new int [][]{
new int []{ 0 , 1 , 0 },
new int []{ 1 , 1 , 0 }
};
int queries[][] = new int [][]{
new int []{ 1 , 1 , 2 , 3 },
new int []{ 1 , 1 , 1 , 1 },
new int []{ 1 , 2 , 2 , 3 }
};
int dp[][] = new int [(matrix.length + 2 )][(matrix[ 0 ].length + 2 )];
queries_fxn(matrix, queries, dp);
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( "]" );
}
}
|
Python3
def modifyDP(matrix, dp):
for j in range ( 1 , len (matrix) + 1 ):
for k in range ( 1 , len (matrix[ 0 ]) + 1 ):
dp[j][k] = dp[j][k] + dp[j - 1 ][k] \
+ dp[j][k - 1 ] - dp[j - 1 ][k - 1 ]
if dp[j][k] % 2 ! = 0 :
matrix[j - 1 ][k - 1 ] = int (matrix[j - 1 ][k - 1 ]) ^ 1
def queries_fxn(matrix, queries, dp):
for q in queries:
x1, y1, x2, y2 = q
dp[x1][y1] + = 1
dp[x2 + 1 ][y2 + 1 ] + = 1
dp[x1][y2 + 1 ] - = 1
dp[x2 + 1 ][y1] - = 1
modifyDP(matrix, dp)
matrix = [[ 0 , 1 , 0 ], [ 1 , 1 , 0 ]]
queries = [[ 1 , 1 , 2 , 3 ], \
[ 1 , 1 , 1 , 1 ], \
[ 1 , 2 , 2 , 3 ]]
dp = [[ 0 for i in range ( len (matrix[ 0 ]) + 2 )] \
for j in range ( len (matrix) + 2 )]
queries_fxn(matrix, queries, dp)
print (matrix)
|
C#
using System;
class GFG
{
static void ModifyDP( int [,] matrix, int [,] dp)
{
for ( int j = 1; j <= matrix.GetLength(0); j++)
{
for ( int k = 1; k <= matrix.GetLength(1); k++)
{
dp[j, k] = dp[j, k] + dp[j - 1, k] + dp[j, k - 1] - dp[j - 1, k - 1];
if (dp[j, k] % 2 != 0)
{
matrix[j - 1, k - 1] = matrix[j - 1, k - 1] ^ 1;
}
}
}
}
static void QueriesFxn( int [,] matrix, int [,] queries, int [,] dp)
{
for ( int i = 0; i < queries.GetLength(0); i++)
{
int x1 = queries[i, 0];
int y1 = queries[i, 1];
int x2 = queries[i, 2];
int y2 = queries[i, 3];
dp[x1, y1] += 1;
dp[x2 + 1, y2 + 1] += 1;
dp[x1, y2 + 1] -= 1;
dp[x2 + 1, y1] -= 1;
}
ModifyDP(matrix, dp);
}
public static void Main( string [] args)
{
int [,] matrix = new int [,] { { 0, 1, 0 }, { 1, 1, 0 } };
int [,] queries = new int [,] { { 1, 1, 2, 3 }, { 1, 1, 1, 1 }, { 1, 2, 2, 3 } };
int [,] dp = new int [(matrix.GetLength(0) + 2, matrix.GetLength(1) + 2)];
QueriesFxn(matrix, queries, dp);
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.GetLength(0) - 1)
{
Console.Write( "]" );
}
else
{
Console.Write( "], " );
}
}
Console.Write( "]" );
}
}
|
Javascript
function modifyDP(matrix, dp)
{
let row = matrix.length;
let col = matrix[0].length;
for (let j = 1; j <= row; j++) {
for (let k = 1; k <= col; k++) {
dp[j][k] = dp[j][k] + dp[j - 1][k]
+ dp[j][k - 1] - dp[j - 1][k - 1];
if (dp[j][k] % 2 != 0) {
matrix[j - 1][k - 1]
= matrix[j - 1][k - 1] ^ 1;
}
}
}
}
function queries_fxn(matrix, queries, dp)
{
for (let i = 0; i < queries.length; i++) {
let x1 = queries[i][0];
let y1 = queries[i][1];
let x2 = queries[i][2];
let y2 = queries[i][3];
dp[x1][y1] += 1;
dp[x2 + 1][y2 + 1] += 1;
dp[x1][y2 + 1] -= 1;
dp[x2 + 1][y1] -= 1;
}
modifyDP(matrix, dp);
}
let matrix = [[0, 1, 0 ], [ 1, 1, 0]];
let queries = [ [ 1, 1, 2, 3 ],[1, 1, 1, 1 ],[1, 2, 2, 3 ]];
let dp= new Array(matrix.length + 2);
for (let i=0; i<matrix.length+2; i++)
dp[i]= new Array(matrix[0].length+2).fill(0);
queries_fxn(matrix, queries, dp);
document.write( "[" );
for (let i = 0; i < matrix.length; i++) {
document.write( "[" );
for (let j = 0; j < matrix[i].length; j++) {
document.write(matrix[i][j] + " " );
}
if (i == matrix.length - 1) {
document.write( "]" );
}
else {
document.write( "], " );
}
}
|
Output:
[[0, 1, 0], [0, 1, 0]]
Time Complexity: O(N * M )
Auxiliary Space: O(N * M)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...