Nearest 1 in a binary matrix
Last Updated :
11 Sep, 2023
Given a binary matrix of order m*n, the task is to find the distance of the nearest 1 for each 0 in the matrix and print the final distance matrix. From any cell (i,j), we can move only in four directions up, down, left and right.
Note: Distance from one cell to immediate another cell is always incremented by 1.
Examples:
Input : m = 3, n = 4
mat[m][n] = {{0, 0, 0, 1},
{0, 0, 1, 1},
{0, 1, 1, 0}}
Output: 3 2 1 0
2 1 0 0
1 0 0 1
A simple brute force solution for this problem is to for each 0 in the matrix, recursively call either DFS or BFS function to check the nearest 1 in the matrix.
Here we are using the dfs approach to calculate the distance of nearest ‘1’.
Implementation: Following is the implementation of above algorithm.
C++
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1000;
int dist[MAX][MAX];
int dfs( int mat[][MAX], int m, int n, int i, int j,vector<vector< bool >> visited)
{
if (i<0||j<0||i>=m||j>=n||visited[i][j]== true )
return MAX;
if (mat[i][j]==1) return 0;
visited[i][j]= true ;
int val=1+min(dfs(mat,m,n,i+1,j,visited),min(dfs(mat,m,n,i-1,j,visited),
min(dfs(mat,m,n,i,j+1,visited),dfs(mat,m,n,i,j-1,visited))));
visited[i][j]= false ;
return val;
}
void nearestOne( int mat[][MAX], int m, int n)
{
vector<vector< bool >> visited(m,vector< bool >(n, false ));
for ( int i=0;i<m;i++)
{
for ( int j=0;j<n;j++)
{
if (mat[i][j]==0)
dist[i][j]=dfs(mat,m,n,i,j,visited);
}
}
return ;
}
int main()
{
int m = 3, n = 4;
int mat[][MAX] = {{0, 0, 0, 1},
{0, 0, 1, 1},
{0, 1, 1, 0}
};
nearestOne(mat, m, n);
for ( int i=0; i<m; i++)
{
for ( int j=0; j<n; j++)
cout << dist[i][j] << " " ;
cout << endl;
}
return 0;
}
|
Java
import java.io.*;
class GFG {
static int MAX = 1000 ;
static int dist[][] = new int [MAX][MAX];
static int dfs( int mat[][], int m, int n, int i, int j, boolean visited[][])
{
if (i < 0 || j < 0 || i >= m ||
j >= n || visited[i][j] == true )
return MAX;
if (mat[i][j] == 1 ) return 0 ;
visited[i][j] = true ;
int val= 1 +Math.min(dfs(mat, m, n, i + 1 , j, visited),
Math.min(dfs(mat, m, n, i - 1 , j, visited),
Math.min(dfs(mat, m, n, i, j + 1 , visited),
dfs(mat, m, n, i, j - 1 , visited))));
visited[i][j] = false ;
return val;
}
static void nearestOne( int mat[][], int m, int n)
{
boolean visited[][] = new boolean [m][n];
for ( int i = 0 ; i < m; i++)
{
for ( int j = 0 ; j < n; j++)
{
visited[i][j] = false ;
}
}
for ( int i = 0 ; i < m; i++)
{
for ( int j = 0 ; j < n; j++)
{
if (mat[i][j] == 0 )
dist[i][j] = dfs(mat, m, n, i, j, visited);
}
}
return ;
}
public static void main(String args[])
{
int m = 3 , n = 4 ;
int mat[][] = {{ 0 , 0 , 0 , 1 },
{ 0 , 0 , 1 , 1 },
{ 0 , 1 , 1 , 0 }
};
nearestOne(mat, m, n);
for ( int i = 0 ; i < m; i++)
{
for ( int j = 0 ; j < n; j++)
System.out.print(dist[i][j] + " " );
System.out.println();
}
}
}
|
Python3
MAX = 1000 ;
def dfs(mat, m, n, i, j, visited):
if (i < 0 or j < 0 or i > = m or j > = n or visited[i][j] = = True ):
return MAX ;
if (mat[i][j] = = 1 ):
return 0 ;
visited[i][j] = True ;
val = 1 + min (dfs(mat,m,n,i + 1 ,j,visited), min (dfs(mat,m,n,i - 1 ,j,visited), min (dfs(mat,m,n,i,j + 1 ,visited),dfs(mat,m,n,i,j - 1 ,visited))));
visited[i][j] = False ;
return val;
def nearestOne(mat, m, n,dist):
visited = [[ False ] * n for _ in range (m)]
for i in range (m):
for j in range (n):
if (mat[i][j] = = 0 ):
dist[i][j] = dfs(mat,m,n,i,j,visited);
return ;
m = 3
n = 4 ;
mat = [[ 0 , 0 , 0 , 1 ], [ 0 , 0 , 1 , 1 ], [ 0 , 1 , 1 , 0 ]];
dist = [[ 0 ] * n for _ in range (m)]
nearestOne(mat, m, n,dist);
print (dist);
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int MAX = 1000;
static int [, ] dist = new int [MAX, MAX];
static int dfs( int [, ] mat, int m, int n, int i, int j, bool [, ] visited)
{
if (i < 0 || j < 0 || i >= m ||
j >= n || visited[i, j] == true )
return MAX;
if (mat[i, j] == 1) return 0;
visited[i, j] = true ;
int val=1+Math.Min(dfs(mat, m, n, i + 1, j, visited),
Math.Min(dfs(mat, m, n, i - 1, j, visited),
Math.Min(dfs(mat, m, n, i, j + 1, visited),
dfs(mat, m, n, i, j - 1, visited))));
visited[i, j] = false ;
return val;
}
static void nearestOne( int [,] mat, int m, int n)
{
bool [,] visited = new bool [m, n];
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
{
visited[i, j] = false ;
}
}
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
{
if (mat[i, j] == 0)
dist[i, j] = dfs(mat, m, n, i, j, visited);
}
}
return ;
}
public static void Main( string [] args)
{
int m = 3, n = 4;
int [,] mat = {{0, 0, 0, 1},
{0, 0, 1, 1},
{0, 1, 1, 0}
};
nearestOne(mat, m, n);
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
Console.Write(dist[i, j] + " " );
Console.WriteLine();
}
}
}
|
Javascript
let MAX = 1000;
function dfs(mat, m, n, i, j, visited)
{
if (i<0||j<0||i>=m||j>=n|| visited[i][j]== true )
return MAX;
if (mat[i][j]==1)
return 0;
visited[i][j]= true ;
let val=1+Math.min(dfs(mat,m,n,i+1,j,visited),Math.min(dfs(mat,m,n,i-1,j,visited),
Math.min(dfs(mat,m,n,i,j+1,visited),dfs(mat,m,n,i,j-1,visited))));
visited[i][j]= false ;
return val;
}
function nearestOne(mat, m, n,dist)
{
let visited = new Array(m);
for (let i=0;i<m;i++)
visited[i]= new Array(n);
for (let i=0;i<m;i++)
for (let j=0;j<n;j++)
visited[i][j]= false ;
for (let i=0;i<m;i++)
{
for (let j=0;j<n;j++)
{
if (mat[i][j]==0)
dist[i][j]=dfs(mat,m,n,i,j,visited);
}
}
return ;
}
let m = 3, n = 4;
let mat = [[0, 0, 0, 1],
[0, 0, 1, 1],
[0, 1, 1, 0]];
let dist = new Array(m);
for (let i=0;i<m;i++)
dist[i]= new Array(n);
for (let i=0;i<m;i++)
for (let j=0;j<n;j++)
dist[i][j] = 0;
nearestOne(mat, m, n,dist);
console.log(dist);
|
Output
3 2 1 0
2 1 0 0
1 0 0 1
Time Complexity: Time complexity of above algorithm is O(m*n)*O(m+n), where m and n are no. of rows and columns of matrix . since we have used two loops for traversing through each cell of matrix which will take O(m*n) and for calling DFS function for the cell having 0 which will take O(m+n) . In worst case all the cell contains 0 . so, we have to call DFS function for each cell which increase the time complexity .
So, This algorithm will might gives Time Limit Exceed for some of the testcases.
An efficient solution for this problem is to use BFS. Here is the algorithm to solve this problem :
- Take distance matrix dist[m][n] and initialize it with INT_MAX.
- Now traverse the matrix and make_pair(i,j) of indices of cell (i, j) having value ‘1’ and push this pair into queue and update dist[i][j] = 0 because distance of ‘1’ from itself will be always 0.
- Now pop elements from queue one by one until it gets empty and call BFS on it.
- Here we need to find the distance of nearest one and we are calling BFS for the cells having ‘1’, so whenever we take adjacent of popped element from queue, we try to minimize the distance by putting condition if (dist[i][j]+1) < dist[ADCi][ADCj]. Then we update the distance of adjacent element in the distance matrix and push this adjacent in the queue to complete the BFS traversal and filling the complete distance matrix.
- After completing the BFS traversal each cell of distance matrix will contain the distance of nearest ‘1’.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX = 1000;
int dist[MAX][MAX];
void nearestOne( int mat[][MAX], int m, int n)
{
int newx[] = { -1, 0, 1, 0 };
int newy[] = { 0, -1, 0, 1 };
queue<pair< int , int > > q;
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++) {
dist[i][j] = INT_MAX;
if (mat[i][j] == 1) {
dist[i][j] = 0;
q.push(make_pair(i, j));
}
}
}
pair< int , int > popped;
while (!q.empty()) {
popped = q.front();
q.pop();
int x = popped.first;
int y = popped.second;
for ( int i = 0; i < 4; i++) {
int adjx = x + newx[i];
int adjy = y + newy[i];
if (adjx >= 0 && adjx < m && adjy >= 0
&& adjy < n
&& dist[adjx][adjy] > dist[x][y] + 1) {
dist[adjx][adjy] = dist[x][y] + 1;
q.push(make_pair(adjx, adjy));
}
}
}
}
int main()
{
int m = 3, n = 4;
int mat[][MAX] = { { 0, 0, 0, 1 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 0 } };
nearestOne(mat, m, n);
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++)
cout << dist[i][j] << " " ;
cout << endl;
}
return 0;
}
|
Java
import java.util.*;
class gfg2 {
static int MAX = 1000 ;
static class pair {
int first, second;
pair( int f, int s)
{
first = f;
second = s;
}
}
static int [][] dist;
static void nearestOne( int mat[][], int m, int n)
{
int newx[] = { - 1 , 0 , 1 , 0 };
int newy[] = { 0 , - 1 , 0 , 1 };
Queue<pair> q = new ArrayDeque<>();
for ( int i = 0 ; i < m; i++) {
for ( int j = 0 ; j < n; j++) {
dist[i][j] = Integer.MAX_VALUE;
if (mat[i][j] == 1 ) {
dist[i][j] = 0 ;
q.add( new pair(i, j));
}
}
}
pair popped;
while (!q.isEmpty()) {
popped = q.peek();
q.remove();
int x = popped.first;
int y = popped.second;
for ( int i = 0 ; i < 4 ; i++) {
int adjx = x + newx[i];
int adjy = y + newy[i];
if (adjx >= 0 && adjx < m && adjy >= 0
&& adjy < n
&& dist[adjx][adjy] > dist[x][y] + 1 ) {
dist[adjx][adjy] = dist[x][y] + 1 ;
q.add( new pair(adjx, adjy));
}
}
}
}
public static void main(String[] args)
{
int m = 3 , n = 4 ;
dist = new int [MAX][MAX];
int mat[][] = { { 0 , 0 , 0 , 1 },
{ 0 , 0 , 1 , 1 },
{ 0 , 1 , 1 , 0 } };
nearestOne(mat, m, n);
for ( int i = 0 ; i < m; i++) {
for ( int j = 0 ; j < n; j++)
System.out.print(dist[i][j] + " " );
System.out.println();
}
}
}
|
Python3
MAX = 1000
INT_MAX = ( 2 * * 32 )
dist = [[ 0 for i in range ( MAX )] for j in range ( MAX )]
def nearestOne(mat, m, n):
newx = [ - 1 , 0 , 1 , 0 ]
newy = [ 0 , - 1 , 0 , 1 ]
q = []
for i in range (m):
for j in range (n):
dist[i][j] = INT_MAX
if (mat[i][j] = = 1 ):
dist[i][j] = 0
q.append([i, j])
popped = []
while ( len (q)):
popped = q[ 0 ]
q.pop( 0 )
x = popped[ 0 ]
y = popped[ 1 ]
for i in range ( 4 ):
adjx = x + newx[i]
adjy = y + newy[i]
if (adjx > = 0 and adjx < m and adjy > = 0 and
adjy < n and dist[adjx][adjy] > dist[x][y] + 1 ):
dist[adjx][adjy] = dist[x][y] + 1
q.append([adjx, adjy])
m = 3
n = 4
mat = [[ 0 , 0 , 0 , 1 ], [ 0 , 0 , 1 , 1 ], [ 0 , 1 , 1 , 0 ]]
nearestOne(mat, m, n)
for i in range (m):
for j in range (n):
print (dist[i][j], end = " " )
print ()
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class gfg2 {
static int MAX = 1000;
public class pair {
public int first, second;
public pair( int f, int s)
{
first = f;
second = s;
}
}
static int [, ] dist;
static void nearestOne( int [, ] mat, int m, int n)
{
int [] newx = { -1, 0, 1, 0 };
int [] newy = { 0, -1, 0, 1 };
Queue<pair> q = new Queue<pair>();
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++) {
dist[i, j] = Int32.MaxValue;
if (mat[i, j] == 1) {
dist[i, j] = 0;
q.Enqueue( new pair(i, j));
}
}
}
pair popped;
while (q.Count != 0) {
popped = q.Peek();
q.Dequeue();
int x = popped.first;
int y = popped.second;
for ( int i = 0; i < 4; i++) {
int adjx = x + newx[i];
int adjy = y + newy[i];
if (adjx >= 0 && adjx < m && adjy >= 0
&& adjy < n
&& dist[adjx, adjy] > dist[x, y] + 1) {
dist[adjx, adjy] = dist[x, y] + 1;
q.Enqueue( new pair(adjx, adjy));
}
}
}
}
public static void Main( string [] args)
{
int m = 3, n = 4;
dist = new int [MAX, MAX];
int [, ] mat = { { 0, 0, 0, 1 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 0 } };
nearestOne(mat, m, n);
for ( int i = 0; i < m; i++) {
for ( int j = 0; j < n; j++)
Console.Write(dist[i, j] + " " );
Console.WriteLine();
}
}
}
|
Javascript
<script>
const MAX = 1000
INT_MAX = (2**32)
let dist = new Array(MAX).fill(0).map(()=> new Array(MAX).fill(0))
function nearestOne(mat, m, n){
let newx = [-1, 0, 1, 0]
let newy = [0, -1, 0, 1]
let q = []
for (let i=0;i<m;i++){
for (let j=0;j<n;j++){
dist[i][j] = INT_MAX
if (mat[i][j] == 1){
dist[i][j] = 0
q.push([i, j])
}
}
}
let popped = []
while (q.length){
popped = q.shift()
let x = popped[0]
let y = popped[1]
for (let i=0;i<4;i++){
let adjx = x + newx[i]
let adjy = y + newy[i]
if (adjx >= 0 && adjx < m && adjy >= 0 &&
adjy < n && dist[adjx][adjy] > dist[x][y] + 1){
dist[adjx][adjy] = dist[x][y] + 1
q.push([adjx, adjy])
}
}
}
}
let m = 3
let n = 4
let mat= [[0, 0, 0, 1], [0, 0, 1, 1], [0, 1, 1, 0]]
nearestOne(mat, m, n)
for (let i=0;i<m;i++){
for (let j=0;j<n;j++){
document.write(dist[i][j], " " )
}
document.write( "</br>" )
}
</script>
|
Output
3 2 1 0
2 1 0 0
1 0 0 1
Since, we cannot do better than O(m*n) time complexity but we can still do better in space complexity with O(1) space.
The Logic behind this algo is that, if at any cell, if we know the distance of its all four direction cell than we just have to take the minimum of all four direction plus 1 for the current cell to be calculated.
We have to compute from top to bottom and left to right for each cell, but this will left uncomputed for bottom right cells. So, we run this approach in 2 phases, if we get 1 we blindly fill 0 as distance of 1 with 1 is 0 else we take the minimum of top and left cell and add 1 to it.
Now, again run two loop and calculate for bottom to top and right to left cell , but here instead of blindly taking minimum of bottom and right, we will take minimum of current value of cell, right and bottom and add 1 to it.
Below is the implementation of the above approach:
C++
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1000;
void nearestOne( int mat[][MAX], int m, int n)
{
for ( int i=0;i<m;i++)
{
for ( int j=0;j<n;j++)
{
if (mat[i][j]==0)
{
int top=i-1>=0 ? mat[i-1][j]:MAX;
int left=j-1>=0? mat[i][j-1]:MAX;
mat[i][j]=min(top,left)+1;
}
else
{
mat[i][j]=0;
}
}
}
for ( int i=m-1;i>=0;i--)
{
for ( int j=n-1;j>=0;j--)
{
int bottom=i+1<m? mat[i+1][j]:MAX;
int right=j+1<n? mat[i][j+1]:MAX;
mat[i][j]=min(mat[i][j],min(bottom,right)+1);
}
}
return ;
}
int main()
{
int m = 3, n = 4;
int mat[][MAX] = {{0, 0, 0, 1},
{0, 0, 1, 1},
{0, 1, 1, 0}
};
nearestOne(mat, m, n);
for ( int i=0; i<m; i++)
{
for ( int j=0; j<n; j++)
cout << mat[i][j] << " " ;
cout << endl;
}
return 0;
}
|
Java
import java.io.*;
class GFG
{
public static int MAX = 1000 ;
public static void nearestOne( int mat[][], int m, int n)
{
for ( int i = 0 ; i < m; i++)
{
for ( int j = 0 ; j < n; j++)
{
if (mat[i][j] == 0 )
{
int top = i - 1 >= 0 ? mat[i - 1 ][j]:MAX;
int left = j - 1 >= 0 ? mat[i][j - 1 ]:MAX;
mat[i][j] = Math.min(top,left) + 1 ;
}
else
{
mat[i][j] = 0 ;
}
}
}
for ( int i = m - 1 ; i >= 0 ; i--)
{
for ( int j = n - 1 ; j >= 0 ; j--)
{
int bottom = i + 1 <m? mat[i+ 1 ][j]:MAX;
int right = j + 1 <n? mat[i][j+ 1 ]:MAX;
mat[i][j] = Math.min(mat[i][j],Math.min(bottom,right)+ 1 );
}
}
return ;
}
public static void main (String[] args)
{
int m = 3 , n = 4 ;
int [][] mat = { { 0 , 0 , 0 , 1 },
{ 0 , 0 , 1 , 1 },
{ 0 , 1 , 1 , 0 } };
nearestOne(mat, m, n);
for ( int i = 0 ; i < m; i++)
{
for ( int j = 0 ; j < n; j++)
System.out.print(mat[i][j] + " " );
System.out.print( "\n" );
}
}
}
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public static int MAX = 1000;
public static void nearestOne( int [,] mat, int m, int n)
{
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
{
if (mat[i, j] == 0)
{
int top = i - 1 >= 0 ? mat[i - 1, j]:MAX;
int left = j - 1 >= 0? mat[i, j - 1]:MAX;
mat[i, j] = Math.Min(top,left) + 1;
}
else
{
mat[i, j] = 0;
}
}
}
for ( int i = m - 1; i >= 0; i--)
{
for ( int j = n - 1; j >= 0; j--)
{
int bottom = i + 1<m? mat[i+1, j]:MAX;
int right = j + 1<n? mat[i, j+1]:MAX;
mat[i, j] = Math.Min(mat[i, j],Math.Min(bottom,right)+1);
}
}
return ;
}
public static void Main ( string [] args)
{
int m = 3, n = 4;
int [, ] mat = { {0, 0, 0, 1},
{0, 0, 1, 1},
{0, 1, 1, 0} };
nearestOne(mat, m, n);
for ( int i = 0; i < m; i++)
{
for ( int j = 0; j < n; j++)
Console.Write(mat[i, j] + " " );
Console.Write( "\n" );
}
}
}
|
Javascript
let MAX = 1000;
function nearestOne(mat, m, n)
{
for ( var i=0;i<m;i++)
{
for ( var j=0;j<n;j++)
{
if (mat[i][j]==0)
{
var top=i-1>=0 ? mat[i-1][j]:MAX;
var left=j-1>=0? mat[i][j-1]:MAX;
mat[i][j]=Math.min(top,left)+1;
}
else
{
mat[i][j]=0;
}
}
}
for ( var i=m-1;i>=0;i--)
{
for ( var j=n-1;j>=0;j--)
{
var bottom=i+1<m? mat[i+1][j]:MAX;
var right=j+1<n? mat[i][j+1]:MAX;
mat[i][j]=Math.min(mat[i][j],Math.min(bottom,right)+1);
}
}
return ;
}
var m = 3, n = 4;
var mat = [[0, 0, 0, 1],
[0, 0, 1, 1],
[0, 1, 1, 0]
];
nearestOne(mat, m, n);
for ( var i=0; i<m; i++)
console.log(mat[i].join( " " ))
|
Python3
MAX = 1000
def nearestOne(mat, m, n):
for i in range (m):
for j in range (n):
if mat[i][j] = = 0 :
top = mat[i - 1 ][j] if i - 1 > = 0 else MAX
left = mat[i][j - 1 ] if j - 1 > = 0 else MAX
mat[i][j] = min (top, left) + 1
else :
mat[i][j] = 0
for i in range (m - 1 , - 1 , - 1 ):
for j in range (n - 1 , - 1 , - 1 ):
bottom = mat[i + 1 ][j] if i + 1 < m else MAX
right = mat[i][j + 1 ] if j + 1 < n else MAX
mat[i][j] = min (mat[i][j], min (bottom, right) + 1 )
return
m = 3
n = 4
mat = [[ 0 , 0 , 0 , 1 ],
[ 0 , 0 , 1 , 1 ],
[ 0 , 1 , 1 , 0 ]]
nearestOne(mat, m, n)
for i in range (m):
for j in range (n):
print (mat[i][j], end = " " )
print ()
|
Output
3 2 1 0
2 1 0 0
1 0 0 1
Time Complexity: O(m*n), where m and n are the number of rows and columns of the given matrix respectively.
Auxiliary Space: O(1)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...