542. 01 Matrix
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:
- The number of elements of the given matrix will not exceed 10,000.
- There are at least one 0 in the given matrix.
- The cells are adjacent in only four directions: up, down, left and right.
参考:http://blog.youkuaiyun.com/u014688145/article/details/64126559
解决思路
- 对待求矩阵进行一次变换,遇0元素不变,遇1元素设为最大值。
00inf0infinf00inf
inf在此处表示无穷,在Java代码中,用Integer.MAX_VALUE
来表示。在对它变换的同时,由于已经扫描了一遍矩阵,在此过程中还需要记录所有0元素的row,col
值,并放入一个队列中。
接下来是求解的核心了,我们只需要寻找到一种机制能够准确更新该数组就可以了,并且它的更新规则符合题意。刚才的dfs是在一个方向上遍历到底,没法拐弯,问题的关键在于隔壁的1元素是否携带了有效信息供当前节点参考!很明显,dfs方案一条路走到底,每个1元素忽略另外三个方向的信息,所以自然而然无法求出正确的。
而再来看看bfs,用形象的比喻来描述这道题的话,就是一颗石头扔入湖中时,它的影响波及周围,且向四周不断传播它的影响。所以该算法的思想,就是首先把这些石头找出来咯【0元素】,更新规则是,一旦碰到【inf】,我就设一个该【0元素】对【inf】的影响值,此处为1。但由于【0元素】的影响是传递的,所以受它影响的【inf】节点必须得放入队列中,计算下次影响值。碰到【inf】,则+1,但前提是当前【inf】节点的值大于原先的值+1。
第二次更新:
0元素周围的元素均被波及,接下来就是1元素的传递,传递的还是0元素的影响。
第三次更新:
public List<List<Integer>> updateMatrix(List<List<Integer>> matrix) {
if (matrix == null || matrix.size() == 0)
return matrix;
int m = matrix.size();
int n = matrix.get(0).size();
Queue<int[]> q = new LinkedList<>();
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
// 把0元素加入队列中,以备波及影响周围元素
if (matrix.get(i).get(j) == 0)
q.offer(new int[] { i, j });
else
// 设为最大值,方便求0元素影响值
matrix.get(i).set(j, Integer.MAX_VALUE);
}
// 上下左右
int[][] dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
while (!q.isEmpty()) {
int cell[] = q.poll();
for (int[] d : dirs) {
int row = cell[0] + d[0];
int col = cell[1] + d[1];
if (row < 0 || row >= m || col < 0 || col >= n)
continue;
// 上下左右取到的值
int value = matrix.get(row).get(col);
int tmp = matrix.get(cell[0]).get(cell[1]) + 1;
// 如果value小,那说明之前已经更新过,不是max
if (value <= tmp)
continue;
q.offer(new int[] { row, col });
matrix.get(row).set(col, tmp);
}
}
return matrix;
}