Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.

Example 1: 
Input:

0 0 0
0 1 0
0 0 0

Output:

0 0 0
0 1 0
0 0 0

Example 2: 
Input:

0 0 0
0 1 0
1 1 1

Output:

0 0 0
0 1 0
1 2 1

Note:

  1. The number of elements of the given matrix will not exceed 10,000.
  2. There are at least one 0 in the given matrix.
  3. The cells are adjacent in only four directions: up, down, left and right.

这道题给了我们一个只有0和1的矩阵,让我们求每一个1到离其最近的0的距离,其实也就是求一个距离场,而求距离场那么BFS将是不二之选。刚看到此题时,我以为这跟之前那道 Shortest Distance from All Buildings 是一样的,从每一个0开始遍历,不停的更新每一个1的距离,但是这样写下来TLE了。后来我又改变思路,从每一个1开始BFS,找到最近的0,结果还是TLE,气死人。后来逛论坛发现思路是对的,就是写法上可以进一步优化,我们可以首先遍历一次矩阵,将值为0的点都存入queue,将值为1的点改为INT_MAX。之前像什么遍历迷宫啊,起点只有一个,而这道题所有为0的点都是起点,这想法,叼!然后开始BFS遍历,从queue中取出一个数字,遍历其周围四个点,如果越界或者周围点的值小于等于当前值加1,则直接跳过。因为周围点的距离更小的话,就没有更新的必要,否则将周围点的值更新为当前值加1,然后把周围点的坐标加入queue,参见代码如下:

解法一:

class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[].size();
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
queue<pair<int, int>> q;
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (matrix[i][j] == ) q.push({i, j});
else matrix[i][j] = INT_MAX;
}
}
while (!q.empty()) {
auto t = q.front(); q.pop();
for (auto dir : dirs) {
int x = t.first + dir[], y = t.second + dir[];
if (x < || x >= m || y < || y >= n || matrix[x][y] <= matrix[t.first][t.second] + ) continue;
matrix[x][y] = matrix[t.first][t.second] + ;
q.push({x, y});
}
}
return matrix;
}
};

下面这种解法是参考的qswawrq大神的帖子,他想出了一种二次扫描的解法,从而不用使用BFS了。这种解法也相当的巧妙,我们首先建立一个和matrix大小相等的矩阵res,初始化为很大的值,这里我们用INT_MAX-1,为甚么要减1呢,后面再说。然后我们遍历matrix矩阵,当遇到为0的位置,我们将结果res矩阵的对应位置也设为0,这make sense吧,就不多说了。然后就是这个解法的精髓了,如果不是0的地方,我们在第一次扫描的时候,比较其左边和上边的位置,取其中较小的值,再加上1,来更新结果res中的对应位置。这里就明白了为啥我们要初始化为INT_MAX-1了吧,因为这里要加1,如果初始化为INT_MAX就会整型溢出,不过放心,由于是取较小值,res[i][j]永远不会取到INT_MAX,所以不会有再加1溢出的风险。第一次遍历我们比较了左和上的方向,那么我们第二次遍历就要比较右和下的方向,注意两种情况下我们不需要比较,一种是当值为0时,还有一种是当值为1时,这两种情况下值都不可能再变小了,所以没有更新的必要,参见代码如下:

解法二:

class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[].size();
vector<vector<int>> res(m, vector<int>(n, INT_MAX - ));
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (matrix[i][j] == ) res[i][j] = ;
else {
if (i > ) res[i][j] = min(res[i][j], res[i - ][j] + );
if (j > ) res[i][j] = min(res[i][j], res[i][j - ] + );
}
}
}
for (int i = m - ; i >= ; --i) {
for (int j = n - ; j >= ; --j) {
if (res[i][j] != && res[i][j] != ) {
if (i < m - ) res[i][j] = min(res[i][j], res[i + ][j] + );
if (j < n - ) res[i][j] = min(res[i][j], res[i][j + ] + );
}
}
}
return res;
}
};

史蒂芬大神的帖子中,他提出了一种变型的方法,没有再区分左上右下,而是每次都跟左边相比,但是需要每次把矩阵旋转90度。他用python写的解法异常的简洁,貌似python中可以一行代码进行矩阵旋转,但是貌似C++没有这么叼,矩阵旋转写起来还是需要两个for循环,写出来估计也不短,这里就不写了,有兴趣的童鞋可以自己试试写一下,可以贴到留言板上哈~

参考资料:

https://leetcode.com/problems/01-matrix/

https://leetcode.com/problems/01-matrix/discuss/101021/java-solution-bfs

https://leetcode.com/problems/01-matrix/discuss/101039/java-33ms-solution-with-two-sweeps-in-on

https://leetcode.com/problems/01-matrix/discuss/101023/18-line-c-dp-solution-on-easy-to-understand

https://leetcode.com/problems/01-matrix/discuss/101102/short-solution-each-path-needs-at-most-one-turn

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 01 Matrix 零一矩阵的更多相关文章

  1. [Leetcode] 01 Matrix

    问题: https://leetcode.com/problems/01-matrix/#/description 基本思路:广度优先遍历,根据所有最短距离为N的格找到所有距离为N+1的格,直到所有的 ...

  2. [LeetCode] Spiral Matrix II 螺旋矩阵之二

    Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For ...

  3. [Leetcode] spiral matrix ii 螺旋矩阵

    Given an integer n, generate a square matrix filled with elements from 1 to n 2 in spiral order. For ...

  4. [LeetCode] 01 Matrix 题解

    题意 # 思路 我一开始的时候想的是嘴 # 实现 ```cpp // // include "../PreLoad.h" class Solution { public: /** ...

  5. leetcode[73] Set Matrix Zeroes 将矩阵置零

    给定一个矩阵,把零值所在的行和列都置为零.例如: 1 2 3 1 3 1 1 1 操作之后变为 1 3 0 0 0 1 1 方法1: 赋值另存一个m*n的矩阵,在原矩阵为零的值相应置新的矩阵行和列为零 ...

  6. [Leetcode Week10]01 Matrix

    01 Matrix 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/01-matrix/description/ Description Given a ...

  7. LeetCode 562. Longest Line of Consecutive One in Matrix(在矩阵中最长的连续1)$

    Given a 01 matrix M, find the longest line of consecutive one in the matrix. The line could be horiz ...

  8. [leetcode] 542. 01 Matrix (Medium)

    给予一个矩阵,矩阵有1有0,计算每一个1到0需要走几步,只能走上下左右. 解法一: 利用dp,从左上角遍历一遍,再从右下角遍历一遍,dp存储当前位置到0的最短距离. 十分粗心的搞错了col和row,改 ...

  9. leetcode 542. 01 Matrix 、663. Walls and Gates(lintcode) 、773. Sliding Puzzle 、803. Shortest Distance from All Buildings

    542. 01 Matrix https://www.cnblogs.com/grandyang/p/6602288.html 将所有的1置为INT_MAX,然后用所有的0去更新原本位置为1的值. 最 ...

随机推荐

  1. 安装Oracle客户端和plsql

    Oracle 客户端安装 +  pl/sql工具安装配置   Oracle 客户端安装 +  pl/sql工具安装配置 下载oracle客户端,并在本地安装. 11g下载地址为: http://www ...

  2. Python的几个小程序,其实我觉得可以称作初学时的基础算法

    昨天学习的,今天做一下整理,以前学过几天c,感觉什么都没有搞出来,有点泄气,看到Python后试试,从最基本的东西学起,希望不要辜负我的这一点热情. if语句的应用 n=1 while n<5: ...

  3. 算法题丨Longest Consecutive Sequence

    描述 Given an unsorted array of integers, find the length of the longest consecutive elements sequence ...

  4. 福州大学软工1715|W班-启航

    新的一学期即将开启,而在仅剩的几天的时间内,我将为接下来的软工实践助教事宜忙碌起来.要学习的东西很多,要关注的东西也很多. 虽然我现在还在茫然阶段,虽然我对<构建之法>还不太熟悉,但是,我 ...

  5. C语言第三次博客作业

    一.PTA实验作业 1 1.实验代码 int i,N; char sex; float high; scanf("%d",&N); for(i =1;i <=N;i ...

  6. alpha冲刺总结随笔

    前言:前面乱乱糟糟整了一路,到最后终于可以稳定下来了.安安心心做个总结,然后把之后要做的事情都理清楚好了. 新学长似乎是个正经[并不]大腿. 看起来也不用都是一个人或者跟陈华学长两个人对半开了[突然摸 ...

  7. GNU/Hurd笔记整理

    patch 0 关于文件锁支持的解决方案,大部分是由Neal Walfield在2001年完成的.这些补丁由Marcus Brinkmann发表,随后被Michael Banck于2002年修改了部分 ...

  8. velocity学习总结

    什么是velocity velocity是一个基于Java的模板引擎,它可以实现彻底的前后端,前端不允许像jsp那样出现Java代码,而是利用context容器传递变量,在java代码里面我们可以往容 ...

  9. 自制 h5 音乐播放器 可搜索

    闲言碎语: 有好几天没有发表博客了,这也是因为一直开发音乐和完善我的博客项目,好不容易抽出时间总结一下这几天所做的东西,笔试又不断通知,实则匆忙 今天难得逃了一次课,就趁这时间,该写写就写写吧~~ 进 ...

  10. 根据HTML5的新方法 drag & drop 方法实现表格拖拽实例

    上一次学习了html5的drag和drop方法,传送门  就自己写了个例子加深自己对drag和drop的理解.不过一开始不是很简单,遇到了不少问题.还好网络万能的,什么都能查到,总算完成了. 说明和详 ...