zoukankan      html  css  js  c++  java
  • 【leet-code】542. 01 矩阵

    题目描述

    给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。

    两个相邻元素间的距离为 1 。

    示例 1:

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

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

    示例 2:

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

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

    注意:

    1. 给定矩阵的元素个数不超过 10000。
    2. 给定矩阵中至少有一个元素是 0。
    3. 矩阵中的元素只在四个方向上相邻: 上、下、左、右。

    算法

    可以用动态规划或者BFS,如果用DFS有超时的风险。

    BFS

    1. 遍历matrix矩阵,将所有(matrix[i][j]=0)的位置信息((i, j))保存到队列中,所有(matrix[i][j]=1)的将值从1改到定义的无穷大。
    2. 当队列不为空的时候,持续循环:
      • 从队列中弹出一个元素,获取位置信息,将该位置(i,j)的上下左右做个判断,如果某个位置上的值大于matrix[i][j]+1,那么将该值改为matrix[i][j]+1,重新压入队列
      • 进行改值操作的时候注意边界条件

    BFS代码

    #define INF 10000
    
    class Solution {
        vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
            int row = matrix.size();
            if (row == 0)
                return matrix;
            int col = matrix[0].size();
    
            queue<pair<int, int> > myQueue;
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    if (matrix[i][j] == 0)
                        myQueue.push(pair<int, int>(i, j));
                    else
                        matrix[i][j] = INF;
                }
            }
    
            while (!myQueue.empty())
            {
                pair<int, int> rec = myQueue.front();
                myQueue.pop();
    
                if (rec.first-1 >= 0 && matrix[rec.first-1][rec.second] > matrix[rec.first][rec.second]+1)
                {
                    matrix[rec.first-1][rec.second] = matrix[rec.first][rec.second]+1;
                    myQueue.push(pair<int, int>(rec.first-1, rec.second));
                }
    
                if (rec.second-1 >= 0 && matrix[rec.first][rec.second-1] > matrix[rec.first][rec.second]+1)
                {
                    matrix[rec.first][rec.second-1] = matrix[rec.first][rec.second]+1;
                    myQueue.push(pair<int, int>(rec.first, rec.second-1));
                }
    
                if (rec.first+1 < row && matrix[rec.first+1][rec.second] > matrix[rec.first][rec.second]+1)
                {
                    matrix[rec.first+1][rec.second] = matrix[rec.first][rec.second]+1;
                    myQueue.push(pair<int, int>(rec.first+1, rec.second));
                }
    
                if (rec.second+1 < col && matrix[rec.first][rec.second+1] > matrix[rec.first][rec.second]+1)
                {
                    matrix[rec.first][rec.second+1] = matrix[rec.first][rec.second]+1;
                    myQueue.push(pair<int, int>(rec.first, rec.second+1));
                }
            }
            return matrix;
        }
    

    动态规划

    基本的思想就是遍历matrix,如果matrix[i][j]是0的话,dp[i][j]直接为0,否则,它与四周的dp值有关,又因为从左上到右下的更新过程中,只能确定左上角两边的dp值;
    所以要再从右下角往左上角遍历,这样就把dp[i][j]四周的dp值都考虑进去了。

    动态规划代码

    class Solution {
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
            // 两次遍历,左上到右下和右下到左上,更新完的dp就是最终的答案
            int row = matrix.size();
            if (row == 0)
                return matrix;
            int col = matrix[0].size();
            vector<vector<int> > dp(row, vector<int>(col));
    
            if (matrix[0][0] == 0)
                dp[0][0] = 0;
            else
                dp[0][0] = INF;
    
            // 第一次
            for (int i = 1; i < col; i++)
            {
                if (matrix[0][i] == 0)
                    dp[0][i] = 0;
                else
                    dp[0][i] = min(INF, dp[0][i-1] + 1);
            }
    
            for (int i = 1; i < row; i++)
            {
                if (matrix[i][0] == 0)
                    dp[i][0] = 0;
                else
                    dp[i][0] = min(INF, dp[i-1][0] + 1);
            }
    
            for (int i = 1; i < row; i++)
            {
                for (int j = 1; j < col; ++j)
                {
                    if (matrix[i][j] == 0)
                        dp[i][j] = 0;
                    else
                        dp[i][j] = min(INF, min(dp[i-1][j], dp[i][j-1]) + 1);
                }
            }
    
            // 打印第一次更新成果
    //        for (int i = 0; i < row; i++)
    //        {
    //            for (int j = 0; j < col; j++)
    //                cout << dp[i][j] << ' ';
    //            cout << endl;
    //        }
    //
    //        cout << "===========我是分割线===========" << endl;
    
            // 第二次
            for (int i = col - 2; i >= 0; i--)
            {
                if (matrix[row-1][i] == 0)
                    dp[row-1][i] = 0;
                else
                    dp[row-1][i] = min(dp[row-1][i], dp[row-1][i+1] + 1);
            }
    
            for (int i = row - 2; i >= 0; i--)
            {
                if (matrix[i][col-1] == 0)
                    dp[i][col-1] = 0;
                else
                    dp[i][col-1] = min(dp[i][col-1], dp[i+1][col-1] + 1);
            }
    
            for (int i = row - 2; i >= 0; i--)
            {
                for (int j = col - 2; j >= 0; j--)
                {
                    if (matrix[i][j] == 1)
                        dp[i][j] = min(dp[i][j], min(dp[i+1][j], dp[i][j+1]) + 1);
                }
            }
            return dp;
        }
    };
    
  • 相关阅读:
    git保存用户名密码的方式
    解决HP电脑播放视频,暂停后再次播放,前几秒钟会没有声音
    我们本想通过网络了解广袤的世界,而不是陷入推荐的漩涡
    cnblogs回来了
    mysql commit和事务
    服务器重启crontab服务
    linux多个命令行执行
    quick bi 配置即席查询sql 参数
    python 不定长参数
    python 和 mysql 的时间格式化
  • 原文地址:https://www.cnblogs.com/shayue/p/10536435.html
Copyright © 2011-2022 走看看