Thursday, August 17th

Matrix distances

Given a binary matrix, find the distances of non-zero cells to zero cells

Keanu Reeves courtesy of Marybel Le Pape via Wikipedia.  Licensed under Creative Commons Attribution-Share Alike 4.0 International license. No changes made

Finding distances to and from groups of cell nodes brings to mind breadth-first search

We will create a solution matrix and a queue.  Then for each cell with a 0 in the original array, we mark its distance as zero in the solution matrix, and push the cell coordinates onto the queue.  Then, we will iterate through the queue, and for each cell, find untraversed neighbors, update the neighbor's distance in the solution matrix, and push the neighbor to the back of the queue.  This continues until the queue is empty, when all shortest distances have been entered in the solution matrix

Start with variable initialization

    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
        int n=mat.size();
        int m=mat[0].size();
        vector<vector<int> >ans=vector<vector<int> >(n, vector<int>(m, -1));

        int size=0;
        queue<pair<int,int> > q;
        ...
    }

Then iterate through the input matrix, and for each 0 cell in the input matrix, mark its distance to zero in the solution matrix as 0.  Also push each 0 cell onto the queue, and increment the size variable, which tracks the size of the queue.   

    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
            if(mat[i][j]==0) {
                ans[i][j]=0;
                q.push(make_pair(i,j));
                size++;
            }
        }
    }

The size variable will allow us to iterate through the queue for all nodes of the same distance

Next, iterate through nodes pushed onto the queue.  We initialize the variable distance to 1, since the first iteration through the queue will find cells of distance 1 from the 0 cells.  For each entry in the queue, we extract the row and column index

    int dist=1;
    pair<int,int> sqr;
    int r,c;
    while(!q.empty()) {
        for(int i=0; i<size; i++) {
            sqr=q.front();
            q.pop();
            r=sqr.first;
            c=sqr.second;
            ...
        }    
        ...
    }

With the row and column, we check immediate neighbors to see if they've been visited yet, minding boundary conditions.  If not, we update the cell's distance in the answer matrix, and push the neighbor's coordinates onto the queue

        if(r>0) {
            if(ans[r-1][c]==-1) {
                ans[r-1][c]=dist;
                q.push(make_pair(r-1,c));
            }
        }
        if(r<n-1) {
            if(ans[r+1][c]==-1) {
              ans[r+1][c]=dist;
              q.push(make_pair(r+1,c));
            }
        }
        if(c<m-1) {
            if(ans[r][c+1]==-1) {
                ans[r][c+1]=dist;
                q.push(make_pair(r,c+1));
            }
        }
        if(c>0) {
            if(ans[r][c-1]==-1) {
                ans[r][c-1]=dist;
                q.push(make_pair(r,c-1));
            }
        }

After all cells of a given depth have been explored, we update size to the size the queue, and increment distance by 1.  The size variable allows us to only use one queue/data structure for storing cells.

    while(!q.empty()) {
        for(int i=0; i<size; i++) {
            ...
        }
        size=q.size();
        dist++;
    }

Finally, return the answer matrix

    return ans;

Fairly straight forward breadth-first search problem.  The Editorial also had a dynamic programming approach where you make a pass from top-left to bottom-right, then bottom-right to top-left, marking shortest paths along the way

Full code of my breadth first search solution below.  A bit long, but all makes sense

vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
   
    int n=mat.size();
    int m=mat[0].size();

    vector<vector<int> >ans=vector<vector<int> >(n, vector<int>(m, -1));

    int size=0;
    queue<pair<int,int> > q;
    for(int i=0; i<n; i++) {
        for(int j=0; j<m; j++) {
            if(mat[i][j]==0) {
                ans[i][j]=0;
                q.push(make_pair(i,j));
                size++;
            }
        }
    }

    int dist=1;
    pair<int,int> sqr;
    int r,c;
    while(!q.empty()) {
        for(int i=0; i<size; i++) {
            sqr=q.front();
            q.pop();
            r=sqr.first;
            c=sqr.second;
            if(r>0) {
                if(ans[r-1][c]==-1) {
                    ans[r-1][c]=dist;
                    q.push(make_pair(r-1,c));
                }
            }
            if(r<n-1) {
                if(ans[r+1][c]==-1) {
                    ans[r+1][c]=dist;
                    q.push(make_pair(r+1,c));
                }
            }
            if(c<m-1) {
                if(ans[r][c+1]==-1) {
                    ans[r][c+1]=dist;
                    q.push(make_pair(r,c+1));
                }
            }
            if(c>0) {
                if(ans[r][c-1]==-1) {
                    ans[r][c-1]=dist;
                    q.push(make_pair(r,c-1));
                }
            }
        }
        size=q.size();
        dist++;
    }

    return ans;

}

Comments

Popular posts from this blog

Wednesday, September 20th

Monday, September 11th

Tuesday, September 19th