【LeetCode-搜索】01矩阵

题目描述

给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例:

输入:
0 0 0
0 1 0
0 0 0
输出:
0 0 0
0 1 0
0 0 0

输入:
0 0 0
0 1 0
1 1 1
输出:
0 0 0
0 1 0
1 2 1

题目链接: https://leetcode-cn.com/problems/01-matrix/

思路1

bfs可以找到从源点到终点的最短路径,所以对于一个位置,如果当前位置是0,则直接返回0;如果不是0,则使用bfs搜索到0的最短路径。代码如下:

class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        if(matrix.empty()) return {{}};

        vector<vector<int>> ans;
        for(int i=0; i<matrix.size(); i++){
            vector<int> v;
            for(int j=0; j<matrix[i].size(); j++){
                v.push_back(bfs(matrix, i, j));
            }
            ans.push_back(v);
        }
        return ans;
    }

    int bfs(vector<vector<int>> matrix, int i, int j){
        if(matrix[i][j]==0) return 0;

        int rows = matrix.size();
        int cols = matrix[0].size();
        int visit[rows][cols];
        memset(visit, 0, sizeof(visit));
        int dirs[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
        queue<int> qx, qy;
        qx.push(i);
        qy.push(j);
        int dist = 1;
        int curLevelNums = 1;
        int nextLevelNums = 0;
        while(!qx.empty()){
            int x = qx.front(); qx.pop();
            int y = qy.front(); qy.pop();
            visit[x][y] = 1;
            curLevelNums--;
            for(int k=0; k<4; k++){
                int tx = x+dirs[k][0];
                int ty = y+dirs[k][1];
                if(tx>=0 && tx<rows && ty>=0 && ty<cols){
                    if(matrix[tx][ty]==0){
                        return dist;
                    }else if(!visit[tx][ty]){
                        qx.push(tx);
                        qy.push(ty);
                        visit[tx][ty] = 1;
                        nextLevelNums++;
                    }
                }                
            }
            if(curLevelNums==0){
                curLevelNums = nextLevelNums;
                nextLevelNums = 0;
                dist++; // 注意dist增加条件,使用类似于树层次打印的思想
            }
        }
        return dist;
    }
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n)
    n为矩阵中元素的个数。

该方法由于时间复杂度过高导致超时未通过。

思路2

使用和思路1相反的思路。思路1是从非零值开始寻找到零值的最短路径,这样在每个非零的位置都要进行一次搜索,每个位置可能会入队列多次,而如果从0值开始寻找到非零值的距离,则每个节点只会入队列一次。为了从0值开始搜素,我们将所有0的位置加入到队列中,然后bfs。代码如下:

class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        if(matrix.empty()) return {{}};

        int rows = matrix.size();
        int cols = matrix[0].size();
        int visit[rows][cols];
        memset(visit, 0, sizeof(visit));
        vector<vector<int>> dist(rows, vector<int>(cols));
        queue<pair<int, int>> q;
        for(int i=0; i<rows; i++){  // 将所有值为0的坐标加入到队列中
            for(int j=0; j<cols; j++){
                if(matrix[i][j]==0){
                    q.emplace(i, j);
                    visit[i][j] = 1;
                }
            }
        }

        int dirs[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
        while(!q.empty()){
            auto [i, j] = q.front(); q.pop();
            for(int k=0; k<4; k++){
                int x = i+dirs[k][0];
                int y = j+dirs[k][1];
                if(x>=0 && x<rows && y>=0 && y<cols && !visit[x][y]){
                    dist[x][y] = dist[i][j]+1;
                    visit[x][y] = 1;
                    q.emplace(x, y);
                }
            }
        }
        
        return dist;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
    n为矩阵中元素的个数。
posted @ 2020-04-15 22:11  Flix  阅读(138)  评论(0编辑  收藏  举报