算法设计与分析:01 Matrix(Week 14)

学号:16340008

题目:542. 01 Matrix


Question:

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.

Answer:

对于该题,我们可以知道越在1区块内部的元素,距离0越远,相应数字也越大。同时,相邻两个元素的大小差距不会大于1。因此我们可以从0区块开始,往非0区块收敛,逐层往非0区块中心按数字顺序填充。我们需要先将所有的1替换成另外一种标识,以区分已填充与未填充。实际上使用一个新的矩阵进行填充是更好的。我们可以将未填充的部分标记为无穷大。

于是我们先初始化一个等宽高的矩阵,其所有元素均为无穷大:

row = len(matrix)
col = len(matrix[0])
newMatrix = [[float('inf') for i in range(col)] for i in range(row)]

然后进行宽度优先搜索(因为是一层层往非0区内部搜索)。宽度优先搜索我们可以使用队列,对队列头进行搜索,搜索结果加入队列尾。对于宽度优先搜索的第一层,应是所有0元素的坐标,因为我们是从0开始往非0区深入的。于是我们可以遍历原矩阵,将0元素的坐标推进队列,同时将将要返回的数组对应0区赋值为0

queue = collections.deque()
        
for i in range(row):
    for j in range(col):
        if matrix[i][j] == 0:
            newMatrix[i][j] = 0
            queue.append((i,j))

然后我们只需要循环推出队头,搜索推出的节点周围有没有应当比自己大的元素,有则赋值为该节点的+1,并推进队尾。

while queue:
    (r, c) = queue.popleft()
    for (move0, move1) in [(1,0), (-1, 0), (0, 1), (0, -1)]:
        newR, newC = r + move0, c + move1
        if 0 <= newR < row and 0 <= newC < col and newMatrix[r][c] + 1 < newMatrix[newR][newC]:
            newMatrix[newR][newC] = newMatrix[r][c] + 1
            queue.append((newR, newC))

最后返回新矩阵即可。 

以下为完整代码(喊本地测试代码):

import collections
class Solution:
    def updateMatrix(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """
        row = len(matrix)
        col = len(matrix[0])
        newMatrix = [[float('inf') for i in range(col)] for i in range(row)]

        queue = collections.deque()
        
        for i in range(row):
            for j in range(col):
                if matrix[i][j] == 0:
                    newMatrix[i][j] = 0
                    queue.append((i,j))
        
        while queue:
            (r, c) = queue.popleft()
            for (move0, move1) in [(1,0), (-1, 0), (0, 1), (0, -1)]:
                newR, newC = r + move0, c + move1
                if 0 <= newR < row and 0 <= newC < col and newMatrix[r][c] + 1 < newMatrix[newR][newC]:
                    newMatrix[newR][newC] = newMatrix[r][c] + 1
                    queue.append((newR, newC))

        return newMatrix

matrix = [[1, 0, 1, 1, 0, 0, 1, 0, 0, 1], [0, 1, 1, 0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 0, 1, 0, 0, 1, 0, 0], [1, 0, 1, 0, 1, 1, 1, 1, 1, 1], [0, 1, 0, 1, 1, 0, 0, 0, 0, 1], [0, 0, 1, 0, 1, 1, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 0, 1, 1], [1, 0, 0, 0, 1, 1, 1, 1, 0, 1], [1, 1, 1, 1, 1, 1, 1, 0, 1, 0], [1, 1, 1, 1, 0, 1, 0, 0, 1, 1]]
test = Solution()
print(test.updateMatrix(matrix))

Leetcode提交结果: 

算法本质是宽度优先搜索,算法时间复杂度为O(n),n为矩阵总元素数(即长×宽)。 

你可能感兴趣的:(算法设计与分析,Python3)