leetcode20200415每日一题-542.01矩阵

1.题目

在这里插入图片描述

2.题目意思

矩阵由01组成,找出矩阵每个元素到最近的0的距离。显然,0到0的距离就是0.

3.代码

解法一:

class Solution:
    def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
        m, n = len(matrix), len(matrix[0])
        Q = collections.deque([])
        visited = set()
        # 初始化队列,将所有起始点加入
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0:
                    Q.append((i, j))
                    visited.add((i, j))
        # 将所有相邻节点加入队列
        while Q:
            i, j = Q.popleft()
            for x, y in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]:
                if 0 <= x < m and 0 <= y < n and (x, y) not in visited:
                    matrix[x][y] = matrix[i][j] + 1
                    visited.add((x, y))
                    Q.append((x, y))
        return matrix

思路:队列+bfs~

用bfs就得用到队列~就像用dfs就得用到递归。所以,Q = collections.deque([])构建了一个双端队列,可从队列左右增加,删减数值。同时构建一个集合visited来记录哪些元素访问过。

接下来进行初始化,如果矩阵值等于0,加入队列Q,并加入visited。加入visited是因为等于0最近的就是0,就不用再重复计算了。加入队列是因为,从0开始计算周边非0单位的距离。另外,其实visited不用集合,用列表也行,因为只会进去一次,但是居然超出时间限制了。。。查了一下,set的搜索速度快的一批,相当的快,在数据量较大的情况下,能比list快5500倍,而且数据量越大,越快。另外,用个set进行维护实际上就是空间换时间~

接下里就是访问双端队列的每一个元素,每次从队列左边弹出,访问上下左右四个元素。如果该元素没访问过(即not in visited),则该元素距离+1,加入队列。因为他旁边是0嘛。然后这个元素出列的时候,他旁边没访问过的元素就是再+1,就变成2了,这也是实现的关键所在。你品,你细品~

解法二:

class Solution:
    def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
        m, n = len(matrix), len(matrix[0])
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 1:
                    matrix[i][j] = m*n
                if i>0:
                    matrix[i][j] = min(matrix[i][j], matrix[i-1][j]+1)
                if j>0:
                    matrix[i][j] = min(matrix[i][j], matrix[i][j-1]+1)
        
        for i in range(m-1, -1, -1):
            for j in range(n-1, -1, -1):
                if i < m-1:
                    matrix[i][j] = min(matrix[i][j], matrix[i+1][j]+1)
                if j < n-1:
                    matrix[i][j] = min(matrix[i][j], matrix[i][j+1]+1)
        
        return matrix

思路:dp

这个dp很简单,初始化时,0就是0,非0给他换成一个很大的数。原因后面说。

然后正向dp,比较右边和下面的元素(如果存在的话),如果自己小就取自己(比如自己是0),如果别的小,就取别人+1。这就是为啥一开始初始化要换掉的原因。因为我们是原地操作,所以原矩阵的1代表次数是1,新矩阵的1代表的是距离为1,此1非彼1,初始化换大一点实际上就是把距离初始为无穷大。

然后再反向dp,比较左边和上边的元素,就完了。

因为是原地操作,所以内存占用很小,轻易超过100%。

解法三:

思路:dfs

我放弃dfs了,搞半天没搞明白,画图思考发现bfs真好啊,我真是醉了,有机会再来搞把,晕了

总的来说,都还行,冲冲冲~

发布了18 篇原创文章 · 获赞 1 · 访问量 793

猜你喜欢

转载自blog.csdn.net/shuaishuaihyh/article/details/105528375