LeetCode Medium 542 01矩阵 Python

75 篇文章 0 订阅
72 篇文章 0 订阅
def updateMatrix( matrix):
    """
    Sulotion DP Method
    算法:动规
    思路:
        一般的动规是从某个确切的地方出发, 比如一般的二维矩阵的题可能就是从左上角出发去右下角比较直观,
        但是本题并没有这个限制,所以事实上可以从任何一个位置出发,但是不妨就选定从左上出发到右下,因为
        这样的话也一定可以将整个二维矩阵都访问,但是要注意的是,这里仅从坐上到右下一遍是不够的!还需要
        右下到坐上再来一遍!
        ⚠️⚠️⚠️??⚡️?:
            因为一般的递归,是不会产生死循环的,比如从左上到右下的过程中,下一时刻的状态和前一时刻的
        状态一定是分割开来的,但是本题事实上是上下左右四个方向,所以如果一次遍历将四个方向都访问的话
        一定会造成死循环,如下图所示,会有循环依赖的问题!所以要两遍不存在循环依赖的遍历,先左上再右下
            ------------
            | a→|←b→|←c |
            --↓↑--↓↑--↓↑-
            | d→|←e→|←f |
            --↓↑--↓↑--↓↑-
            | g→|←h→|←i |
            -------------
    复杂度分析:
        时间:ORC*2,R是行数,c是列数,其实就是ON2了
        空间:ORC*2,dp数组空间
    """
    if matrix == []:
        return []
    m, n = len(matrix), len(matrix[0])
    dp = [[float('inf')] * n for _ in range(m)]
    for i in range(m):
        for j in range(n):
            if matrix[i][j] == 0:
                dp[i][j] = 0
            else:
                if i > 0:
                    dp[i][j] = min(dp[i][j], dp[i - 1][j] + 1)
                if j > 0:
                    dp[i][j] = min(dp[i][j], dp[i][j - 1] + 1)
    for i in range(m - 1, -1, -1):
        for j in range(n - 1, -1, -1):
            if matrix[i][j] == 0:
                dp[i][j] = 0
            else:
                if i < m - 1:
                    dp[i][j] = min(dp[i][j], dp[i + 1][j] + 1)
                if j < n - 1:
                    dp[i][j] = min(dp[i][j], dp[i][j + 1] + 1)
    return dp

def updateMatrix1( matrix):
    """
    Sulotion Method
    算法:BFS宽度优先遍历
    思路:
        本思路是基于暴力解法来的改进版,所以先看一下暴力解法的思路:
            遍历矩阵,如果matrix[i][j] == 0 的话,ans[i][j]=0,否则matrix[i][j] == 1时从这个1的位置出发
        遍历附近所有的节点,找到最近的0,距离是abs(r-i)+abs(c-i),非常暴力,耗时,并且这样的思路是基于
        ⚠️ ⚠️【一次遍历只更新一个matrix[i][j] == 1位置的ans[i][j]的值】
        所以改进的方法就是,从matrix[i][j] == 0出发,一次更新所有matrix,0附近的所有ans大于它的那些位置的值
        这样一次可以更新多点
            并且要使用BFS来保障一次更新周围紧邻的所有位置,BFS又需要queue,所以这里设置queue来辅助
        注意️?⚡️?:
            BFS的特性是从某点出发,BFS第一次碰到该点的时候一定是经过了最短的搜索步数,可以拿二叉树的层次遍历
        来类比理解。所以从1到0的最短间隔,反过来,也是这个0到这个1的最短间隔,所以从0出发BFS来简化问题

        故:
            1.先遍历一次,然后将所有matrix[i][j] == 0的位置入队列并且设ans[i][j] = 0
            2.对队列中每个位置i,j的四个方向的紧邻位置r,c进行更新,
                位置合法且ans[r][c] > ans[i][j] + 1
                则更新ans[r][c] = ans[i][j] + 1
                并且将r,c入队列,因为刚才只是把所有0入队列了,被更新的新的位置往往都是1,而只遍历所有0的紧邻
                节点可能是无法到达下面的1的,所以这里要把r,c入队列,并且这里的queue本来就是为了BFS,BFS可以
                得到最近的解,也就应该这样逐级入队列
    复杂度分析:
        时间:ORC,
        空间:ORC,ans空间
    """
    if matrix == []:
        return []
    ans = [[float('inf')]*len(matrix[0]) for _ in range(len(matrix))]
    queue = []
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            if matrix[i][j] == 0:
                ans[i][j] = 0
                queue.append((i, j))
    direction = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    while queue:
        i, j = queue.pop(0)
        for i_delta, j_delta in direction:
            r = i + i_delta
            c = j + j_delta
            if r >= 0 and r <= len(matrix) - 1 and c >= 0 and c <= len(matrix[0]) - 1 and ans[r][c] > ans[i][j] + 1:
                ans[r][c] = ans[i][j] + 1
                queue.append((r, c))
    return ans

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值