[LeetCode解题报告] 6081. 到达角落需要移除障碍物的最小数目

一、 题目

1. 题目描述

给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n 。每个单元格都是两个值之一:

0 表示一个 空 单元格,
1 表示一个可以移除的 障碍物 。
你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。

现在你需要从左上角 (0, 0) 移动到右下角 (m - 1, n - 1) ,返回需要移除的障碍物的 最小 数目。

示例 1:

输入:grid = [[0,1,1],[1,1,0],[1,1,0]]
输出:2
解释:可以移除位于 (0, 1) 和 (0, 2) 的障碍物来创建从 (0, 0) 到 (2, 2) 的路径。
可以证明我们至少需要移除两个障碍物,所以返回 2 。
注意,可能存在其他方式来移除 2 个障碍物,创建出可行的路径。
示例 2:

输入:grid = [[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]]
输出:0
解释:不移除任何障碍物就能从 (0, 0) 到 (2, 4) ,所以返回 0 。

提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 105
2 <= m * n <= 105
grid[i][j] 为 0 或 1
grid[0][0] == grid[m - 1][n - 1] == 0

2. 原题链接

链接: 6081. 到达角落需要移除障碍物的最小数目

二、 解题报告

1. 思路分析

这是20220529周赛第四题,没想到这么水,早知道先做这题了。
用优先队列,BestFirst搜就能过。
dijkstra模板题,数据大执行有点慢。

2. 复杂度分析

最坏时间复杂度O(nm)

3. 代码实现

BFS

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0  # 传入顺序
    def push(self, item, priority):
        heapq.heappush(self._queue, (priority, self._index, item))
        self._index += 1
    def pop(self):
        return heapq.heappop(self._queue)[-1]
    def __str__(self):
        return str(self._queue)
    def __len__(self):
        return len(self._queue)
class Solution:
    def minimumObstacles(self, grid: List[List[int]]) -> int:
        m,n = len(grid),len(grid[0])
        q = PriorityQueue()
        q.push((0,0,0),0)
        visited = {(0,0):0}
        while q:
            x,y,z =q.pop()
            if x == m-1 and y == n -1:
                return z
            
            for x1,y1 in [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]:
                if not (0<=x1<m and 0<=y1<n):
                    continue
                if (x1,y1) not in visited or visited[(x1,y1)] > z+grid[x1][y1]:
                    visited[(x1,y1)] = z+grid[x1][y1]
                    q.push((x1,y1,visited[(x1,y1)]),visited[(x1,y1)])
        
        return -1
                    

dijkstra模板。

class Solution:
    def minimumObstacles(self, grid: List[List[int]]) -> int:
        # 最短路模板题
        m,n = len(grid),len(grid[0])
        graph = collections.defaultdict(dict)
        for i in range(m):
            for j in range(n):
                for x,y in [(i+1,j),(i,j+1)]:
                    if x<m and y<n:
                        graph[(i,j)][(x,y)] = grid[x][y]
                        graph[(x,y)][(i,j)] = grid[i][j]

        def dijkstra(graph,start):            
            from queue import PriorityQueue
            dist =  collections.defaultdict(lambda :float("inf"))  # 初始化距离数组
            dist[start] = 0  # 原点到自己是0
            visited = set([start])  # 访问过原点了
            q = PriorityQueue()
            
            for v,w in graph[start].items():  # 找到所有原点的邻居,更新他们的dist
                dist[v] = w
                q.put((w,v))  # 权放前边,注意是put
            while not q.empty():
                x,u = q.get()  # 用u给别的节点做松弛,注意是get
                if u in visited:
                    continue
                visited.add(u)
                for v,w in graph[u].items():
                    new_dist = dist[u]+w
                    if new_dist < dist[v]:
                        dist[v] = new_dist
                        if v not in visited:
                            q.put((new_dist,v))
            return dist
        dist = dijkstra(graph,(0,0))
        return  dist[(m-1,n-1)]
   

三、 本题小结

  1. 最短路。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值