Given a matrix arr[][], consisting of only 0, 1, and 2, that represents an empty ward, an uninfected patient, and an infected patient respectively. In one unit of time, an infected person at index (i, j) can infect an uninfected person adjacent to it i.e., at index (i – 1, j), (i + 1, j), (i, j – 1), and (i, j + 1). The task is to find the minimum amount of time required to infect all the patients. If it is impossible to infect all the patients, then print “-1”.
Examples:
Input: arr[][] = {{2, 1, 0, 2, 1}, {1, 0, 1, 2, 1}, {1, 0, 0, 2, 1}}
Output: 2
Explanation:
At time t = 1: The patients at positions {0, 0}, {0, 3}, {1, 3} and {2, 3} will infect patient at {{0, 1}, {1, 0}, {0, 4}, {1, 2}, {1, 4}, {2, 4}} during 1st unit time.
At time t = 2: The patient at {1, 0} will get infected and will infect patient at {2, 0}.
After the above time intervals all the uninfected patients are infected. Therefore, the total amount of time required is 2.
Input: arr[][] = {{2, 1, 0, 2, 1}, {0, 0, 1, 2, 1}, {1, 0, 0, 2, 1}}
Output: -1
Approach: The given problem can be solved by using BFS Traversal on the 2D matrix. Follow the steps below to solve the given problem:
- Initialize a 2D array, say timeofinfection[][] with -1, such that timeofinfection[i][j] stores the time when the patient at index (i, j) was infected.
- Initialize a queue to store indices of infected patients and their time of infection.
- Traverse the given matrix arr[][] and perform the following operations:
- If the value at cell (i, j) is 2, then push that cell into the queue with the time of infection as 0 i.e., {i, j, 0}.
- Iterate until the queue is non-empty and perform the following steps:
- Pop the front element of the queue and store it in a variable, say current.
- From the current popped cell (i, j), if the adjacent cell has an infected person which is unvisited, then push the index of the adjacent cell with (1 + time of infection of the current popped cell) into the queue.
- After completing the above steps, if all the infected persons are visited, i.e. the time of infection of all the infected persons is non-negative, then print the maximum element present in the matrix timeofinfection[][] as the maximum unit of time required to infect all the patients.
- Otherwise, print “-1”.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector<pair< int , int > > direction
= { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 } };
int maximumTime(vector<vector< int > > arr)
{
int n = arr.size();
int m = arr[0].size();
int timeofinfection[n][m];
queue<pair<pair< int , int >, int > > q;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < m; j++) {
timeofinfection[i][j] = -1;
if (arr[i][j] == 2) {
q.push({ { i, j }, 0 });
timeofinfection[i][j] = 0;
}
}
}
while (!q.empty()) {
pair<pair< int , int >, int > current
= q.front();
q.pop();
for ( auto it : direction) {
int i = current.first.first
+ it.first;
int j = current.first.second
+ it.second;
if (i < 0 || j < 0 || i >= n
|| j >= m || arr[i][j] != 1
|| timeofinfection[i][j] != -1) {
continue ;
}
q.push({ { i, j },
current.second + 1 });
timeofinfection[i][j]
= current.second + 1;
}
}
int maxi = INT_MIN;
int flag = 0;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < m; j++) {
if (arr[i][j] != 1)
continue ;
if (arr[i][j] == 1
&& timeofinfection[i][j] == -1) {
flag = 1;
break ;
}
maxi = max(maxi, timeofinfection[i][j]);
}
}
if (flag)
return -1;
return maxi;
}
int main()
{
vector<vector< int > > arr
= { { 2, 1, 0, 2, 1 },
{ 1, 0, 1, 2, 1 },
{ 1, 0, 0, 2, 1 } };
cout << maximumTime(arr);
return 0;
}
|
Java
import java.util.*;
class GFG {
static class pair
{
int first, second, third;
pair( int first, int second, int third)
{
this .first = first;
this .second = second;
this .third = third;
}
}
static int [][] direction = { { 1 , 0 }, { 0 , - 1 },
{ - 1 , 0 }, { 0 , 1 } };
static int maximumTime( int [][] arr)
{
int n = arr.length;
int m = arr[ 0 ].length;
int [][] timeofinfection = new int [n][m];
Queue<pair> q = new LinkedList<>();
for ( int i = 0 ; i < n; i++)
{
for ( int j = 0 ; j < m; j++)
{
timeofinfection[i][j] = - 1 ;
if (arr[i][j] == 2 )
{
q.add( new pair(i, j, 0 ));
timeofinfection[i][j] = 0 ;
}
}
}
while (!q.isEmpty())
{
pair current = q.peek();
q.poll();
for ( int [] it : direction)
{
int i = current.first + it[ 0 ];
int j = current.second + it[ 1 ];
if (i < 0 || j < 0 || i >= n ||
j >= m || arr[i][j] != 1 ||
timeofinfection[i][j] != - 1 )
{
continue ;
}
q.add( new pair(i, j ,
current.second + 1 ));
timeofinfection[i][j] = current.third + 1 ;
}
}
int maxi = Integer.MIN_VALUE;
int flag = 0 ;
for ( int i = 0 ; i < n; i++)
{
for ( int j = 0 ; j < m; j++)
{
if (arr[i][j] != 1 )
continue ;
if (arr[i][j] == 1 && timeofinfection[i][j] == - 1 )
{
flag = 1 ;
break ;
}
maxi = Math.max(maxi, timeofinfection[i][j]);
}
}
if (flag == 1 )
return - 1 ;
return maxi;
}
public static void main(String[] args)
{
int [][] arr = { { 2 , 1 , 0 , 2 , 1 },
{ 1 , 0 , 1 , 2 , 1 },
{ 1 , 0 , 0 , 2 , 1 } };
System.out.print(maximumTime(arr));
}
}
|
Javascript
<script>
var direction
= [ [ 1, 0 ], [ 0, -1 ], [ -1, 0 ], [ 0, 1 ] ];
function maximumTime(arr)
{
var n = arr.length;
var m = arr[0].length;
var timeofinfection = Array.from(Array(n), ()=>Array(m));
var q = [];
for ( var i = 0; i < n; i++) {
for ( var j = 0; j < m; j++) {
timeofinfection[i][j] = -1;
if (arr[i][j] == 2) {
q.push([ [ i, j ], 0 ]);
timeofinfection[i][j] = 0;
}
}
}
while (q.length!=0) {
var current
= q[0];
q.shift();
for ( var it of direction) {
var i = current[0][0]
+ it[0];
var j = current[0][1]
+ it[1];
if (i < 0 || j < 0 || i >= n
|| j >= m || arr[i][j] != 1
|| timeofinfection[i][j] != -1) {
continue ;
}
q.push([[i, j],
current[1] + 1 ]);
timeofinfection[i][j]
= current[1] + 1;
}
}
var maxi = -1000000000;
var flag = 0;
for ( var i = 0; i < n; i++) {
for ( var j = 0; j < m; j++) {
if (arr[i][j] != 1)
continue ;
if (arr[i][j] == 1
&& timeofinfection[i][j] == -1) {
flag = 1;
break ;
}
maxi = Math.max(maxi, timeofinfection[i][j]);
}
}
if (flag)
return -1;
return maxi;
}
var arr
= [ [ 2, 1, 0, 2, 1 ],
[ 1, 0, 1, 2, 1 ],
[ 1, 0, 0, 2, 1 ] ];
document.write( maximumTime(arr));
</script>
|
Python
def bfs(i, j, mat, time):
mat[i][j] = 0
stack = []
row = [ - 1 , 0 , 0 , 1 ]
col = [ 0 , - 1 , 1 , 0 ]
for k in range ( 4 ):
x = i + row[k]
y = j + col[k]
if x > = 0 and x < r and y > = 0 and y < c and mat[x][y] = = 1 :
mat[x][y] = 0
stack.append((x, y))
time[x][y] = time[i][j] + 1
return stack
def maxTime(hospital):
time = [[ 0 for i in range (c)] for j in range (r)]
que = []
for i in range (r):
for j in range (c):
if hospital[i][j] = = 2 :
que + = bfs(i, j, hospital, time)
while ( len (que) ! = 0 ):
for x, y in que:
temp = bfs(x, y, hospital, time)
que = temp
res = 0
for i in range (r):
for j in range (c):
if hospital[i][j] = = 1 :
return - 1
res = max (res, time[i][j])
return res
hospital = [[ 2 , 1 , 0 , 2 , 1 ],
[ 1 , 0 , 1 , 2 , 1 ],
[ 1 , 0 , 0 , 2 , 1 ]]
r = len (hospital)
c = len (hospital[ 0 ])
print (maxTime(hospital))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public class pair
{
public int first;
public int second;
public int third;
public pair( int first, int second, int third)
{
this .first = first;
this .second = second;
this .third = third;
}
}
static int [][] direction = {
new int [] { 1, 0 },
new int [] { 0, -1 },
new int [] { -1, 0 },
new int [] { 0, 1 }
};
static int maximumTime( int [][] arr)
{
int n = arr.Length;
int m = arr[0].Length;
int [][] timeofinfection = new int [n][];
for ( int i = 0; i < n; i++)
timeofinfection[i] = new int [m];
Queue<pair> q = new Queue<pair>();
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < m; j++)
{
timeofinfection[i][j] = -1;
if (arr[i][j] == 2)
{
q.Enqueue( new pair(i, j, 0));
timeofinfection[i][j] = 0;
}
}
}
while (q.Count != 0)
{
pair current = q.Peek();
q.Dequeue();
foreach ( int [] it in direction)
{
int i = current.first + it[0];
int j = current.second + it[1];
if (i < 0 || j < 0 || i >= n ||
j >= m || arr[i][j] != 1 ||
timeofinfection[i][j] != -1)
{
continue ;
}
q.Enqueue( new pair(i, j,
current.second + 1));
timeofinfection[i][j] = current.third + 1;
}
}
int maxi = int .MinValue;
int flag = 0;
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < m; j++)
{
if (arr[i][j] != 1)
continue ;
if (arr[i][j] == 1 && timeofinfection[i][j] == -1)
{
flag = 1;
break ;
}
maxi = Math.Max(maxi, timeofinfection[i][j]);
}
}
if (flag == 1)
return -1;
return maxi;
}
static void Main( string [] args)
{
int [][] arr = {
new int []{ 2, 1, 0, 2, 1 },
new int []{ 1, 0, 1, 2, 1 },
new int []{ 1, 0, 0, 2, 1 }
};
Console.WriteLine(maximumTime(arr));
}
}
|
Time Complexity: O(N * M)
Auxiliary Space: O(N * M)
Approach 2:This uses the same BFS traversal technique but instead of using an array of integers to keep track of whether all patients are infected, it uses a single integer which reduces overall space consumption and overhead of doing an extra check for uninfected patients.
The basic idea is we will store the count of uninfected persons at the start and as an individual will got infected we will decrement this count. This will remove the overhead of checking for uninfected persons at the end. And the time at which the last person got infected will be our final answer.
C++
#include <bits/stdc++.h>
using namespace std;
vector<pair< int , int > > direction
= { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 } };
int maximumTime(vector<vector< int > > arr)
{
int n = arr.size();
int m = arr[0].size();
vector<vector< bool >> visited(n,vector< bool >(m,0));
queue<pair<pair< int , int >, int > > q;
int uninfected_count=0;
int time = 0;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < m; j++) {
if (arr[i][j] == 2) {
q.push({ { i, j }, 0 });
visited[i][j] = 1;
}
if (arr[i][j] == 1){
uninfected_count++;
}
}
}
while (!q.empty()) {
pair<pair< int , int >, int > current
= q.front();
time = current.second;
q.pop();
for ( auto it : direction) {
int i = current.first.first
+ it.first;
int j = current.first.second
+ it.second;
if (i < 0 || j < 0 || i >= n
|| j >= m || arr[i][j] != 1
|| visited[i][j] != 0) {
continue ;
}
q.push({ { i, j }, time + 1 });
visited[i][j] = 1;
uninfected_count--;
}
}
if (uninfected_count != 0)
return -1;
return time ;
}
int main()
{
vector<vector< int > > arr
= { { 2, 1, 0, 2, 1 },
{ 1, 0, 1, 2, 1 },
{ 1, 0, 0, 2, 1 } };
cout << maximumTime(arr);
return 0;
}
|
Java
import java.util.*;
public class GFG{
static class pair
{
int first, second, third;
pair( int first, int second, int third)
{
this .first = first;
this .second = second;
this .third = third;
}
}
static int direction[][] = { { 1 , 0 }, { 0 , - 1 },
{ - 1 , 0 }, { 0 , 1 } };
static int maximumTime( int arr[][])
{
int n = arr.length;
int m = arr[ 0 ].length;
boolean visited[][] = new boolean [n][m];
Queue<pair> q = new LinkedList<>();
int uninfected_count= 0 ;
int time = 0 ;
for ( int i = 0 ; i < n; i++) {
for ( int j = 0 ; j < m; j++) {
if (arr[i][j] == 2 ) {
q.add( new pair(i, j, 0 ));
visited[i][j] = true ;
}
if (arr[i][j] == 1 ){
uninfected_count++;
}
}
}
while (!q.isEmpty()) {
pair current = q.peek();
time = current.third;
q.poll();
for ( int [] it : direction) {
int i = current.first
+ it[ 0 ];
int j = current.second
+ it[ 1 ];
if (i < 0 || j < 0 || i >= n
|| j >= m || arr[i][j] != 1
|| visited[i][j]) {
continue ;
}
q.add( new pair( i, j, time + 1 ));
visited[i][j] = true ;
uninfected_count--;
}
}
if (uninfected_count != 0 )
return - 1 ;
return time;
}
public static void main(String args[])
{
int arr[][] = { { 2 , 1 , 0 , 2 , 1 },
{ 1 , 0 , 1 , 2 , 1 },
{ 1 , 0 , 0 , 2 , 1 } };
System.out.println(maximumTime(arr));
}
}
|
Python
direction = [( 1 , 0 ), ( 0 , - 1 ), ( - 1 , 0 ), ( 0 , 1 )]
def maximumTime(arr):
n = len (arr)
m = len (arr[ 0 ])
visited = [[ False for j in range (m)] for i in range (n)]
q = []
uninfected_count = 0
time = 0
for i in range (n):
for j in range (m):
if arr[i][j] = = 2 :
q.append(((i, j), 0 ))
visited[i][j] = True
if arr[i][j] = = 1 :
uninfected_count + = 1
while q:
current = q.pop( 0 )
time = current[ 1 ]
for it in direction:
i = current[ 0 ][ 0 ] + it[ 0 ]
j = current[ 0 ][ 1 ] + it[ 1 ]
if i < 0 or j < 0 or i > = n or j > = m or arr[i][j] ! = 1 or visited[i][j]:
continue
q.append(((i, j), time + 1 ))
visited[i][j] = True
uninfected_count - = 1
if uninfected_count ! = 0 :
return - 1
return time
arr = [[ 2 , 1 , 0 , 2 , 1 ], [ 1 , 0 , 1 , 2 , 1 ], [ 1 , 0 , 0 , 2 , 1 ]]
print (maximumTime(arr))
|
Javascript
let direction = [
[1, 0],
[0, -1],
[-1, 0],
[0, 1]
];
function maximumTime(arr) {
let n = arr.length;
let m = arr[0].length;
let visited = Array(n).fill().map(() => Array(m).fill( false ));
let q = [];
let uninfected_count = 0;
let time = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (arr[i][j] === 2) {
q.push([
[i, j], 0
]);
visited[i][j] = true ;
}
if (arr[i][j] === 1) {
uninfected_count += 1;
}
}
}
while (q.length > 0) {
let current = q.shift();
time = current[1];
for (let it of direction) {
let i = current[0][0] + it[0];
let j = current[0][1] + it[1];
if (i < 0 || j < 0 || i >= n || j >= m || arr[i][j] !== 1 || visited[i][j]) {
continue ;
}
q.push([
[i, j], time + 1
]);
visited[i][j] = true ;
uninfected_count -= 1;
}
}
if (uninfected_count !== 0) {
return -1;
}
return time;
}
let arr = [
[2, 1, 0, 2, 1],
[1, 0, 1, 2, 1],
[1, 0, 0, 2, 1]
];
console.log(maximumTime(arr));
|
C#
using System;
using System.Collections.Generic;
public struct Pair
{
public int first, second, third;
public Pair( int first, int second, int third)
{
this .first = first;
this .second = second;
this .third = third;
}
}
public class GFG {
static int [][] direction
= { new int [] { 1, 0 }, new int [] { 0, -1 },
new int [] { -1, 0 }, new int [] { 0, 1 } };
static int MaximumTime( int [][] arr)
{
int n = arr.Length;
int m = arr[0].Length;
bool [, ] visited = new bool [n, m];
var q = new Queue<Pair>();
int uninfected_count = 0;
int time = 0;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < m; j++) {
if (arr[i][j] == 2) {
q.Enqueue( new Pair(i, j, 0));
visited[i, j] = true ;
}
if (arr[i][j] == 1) {
uninfected_count++;
}
}
}
while (q.Count > 0) {
var current = q.Peek();
time = current.third;
q.TryDequeue( out current);
for ( int i = 0; i < 4; i++) {
int x = current.first + direction[i][0];
int y = current.second + direction[i][1];
if (x < 0 || y < 0 || x >= n || y >= m
|| arr[x][y] != 1 || visited[x, y]) {
continue ;
}
q.Enqueue( new Pair(x, y, time + 1));
visited[x, y] = true ;
uninfected_count--;
}
}
if (uninfected_count != 0) {
return -1;
}
return time;
}
public static void Main( string [] args)
{
int [][] arr = { new int [] { 2, 1, 0, 2, 1 },
new int [] { 1, 0, 1, 2, 1 },
new int [] { 1, 0, 0, 2, 1 } };
Console.WriteLine(MaximumTime(arr));
}
}
|
Time Complexity: O(n*m)
Auxiliary Space: O(n*m)