【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;
    }
};

转载于:https://www.cnblogs.com/shayue/p/10536435.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
探险家小扣的行动轨迹,都将保存在记录仪中。expeditions[i] 表示小扣第 i 次探险记录,用一个字符串数组表示。其中的每个「营地」由大小写字母组成,通过子串 -> 连接。例:"Leet->code->Campsite",表示到访了 "Leet"、"code"、"Campsite" 三个营地。expeditions[0] 包含了初始小扣已知的所有营地;对于之后的第 i 次探险(即 expeditions[i] 且 i > 0),如果记录中包含了之前均没出现的营地,则表示小扣 新发现 的营地。 请你找出小扣发现新营地最多且索引最小的那次探险,并返回对应的记录索引。如果所有探险记录都没有发现新的营地,返回 -1。注意: 大小写不同的营地视为不同的营地; 营地的名称长度均大于 0。用python实现。给你几个例子:示例 1: 输入:expeditions = ["leet->code","leet->code->Campsite->Leet","leet->code->leet->courier"] 输出:1 解释: 初始已知的所有营地为 "leet" 和 "code" 第 1 次,到访了 "leet"、"code"、"Campsite"、"Leet",新发现营地 2 处:"Campsite"、"Leet" 第 2 次,到访了 "leet"、"code"、"courier",新发现营地 1 处:"courier" 第 1 次探险发现的新营地数量最多,因此返回 1。示例 2: 输入:expeditions = ["Alice->Dex","","Dex"] 输出:-1 解释: 初始已知的所有营地为 "Alice" 和 "Dex" 第 1 次,未到访任何营地; 第 2 次,到访了 "Dex",未新发现营地; 因为两次探险均未发现新的营地,返回 -1
最新发布
04-23

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值