Day3: GG高频面经 | LC1293 Shortest Path in a Grid with Obstacles Elimination|Sundri |最短路径 Bellmanford

Shortest Path in a Grid with Obstacles Elimination - LeetCode

You are given an m x n integer matrix grid where each cell is either 0 (empty) or 1 (obstacle). You can move up, down, left, or right from and to an empty cell in one step.

Return the minimum number of steps to walk from the upper left corner (0, 0) to the lower right corner (m - 1, n - 1) given that you can eliminate at most k obstacles. If it is not possible to find such walk return -1.

Example 1:

Input: grid = [[0,0,0],[1,1,0],[0,0,0],[0,1,1],[0,0,0]], k = 1
Output: 6
Explanation: 
The shortest path without eliminating any obstacle is 10.
The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2).

Example 2:

Input: grid = [[0,1,1],[1,1,1],[1,0,0]], k = 1
Output: -1
Explanation: We need to eliminate at least two obstacles to find such a walk.

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 40
  • 1 <= k <= m * n
  • grid[i][j] is either 0 or 1.
  • grid[0][0] == grid[m - 1][n - 1] == 0

# 如果这道题拿来面试,可以先问哪些限制问题?

1.grid[i][j]里面row和col的长度范围是多少?值是只有0和1吗?

2.k的范围是多少?

3.终止条件是什么

# 解题关键:

1. queue 记录四个参数: ( 当前步数 , ( 当前行, 当前列,  剩余可以用的移动值))

2. visited 记录三个参数:(当前行,当前列,剩余可以用的移动值)

3. 边界条件:如果k的大小已经等于或超过 (row+col -2),最短路径就是 row + col -2 

# 为什么 k >= row + col -2, 最短路径就是 row + col -2 ?

为什么不是 row + col ?因为我们算的是从第一个点移动到最后一个点的距离,所以我们算的是有多少个间隔,而不是有多少个点。如果k足够大,最短距离应该就是矩阵两边之和-1,但是因为我们是从第一个格子出发,因此要把这个格子排除掉。

区分两个概念:格子总数,以及步数

格子总数:row + col -1 

最短步数: row + col - 2

# 为什么set和queue都要记录下当前k的值?

假设k足够大,那就会存在这样的情况,1->2, 当前点是(0,2,k=原始设定值;也可能是 1->4->5->2,相当于是兜了一圈之后又回到了2,如果queue里面只记录了当前的行和列,就会忽略掉到达同一个点,但是对 K的消耗值不同的情况。因此也需要同时记录下对K的消耗。

# 解题代码

class Solution(object):
    def shortestPath(self, grid, k):
        # 直接bfs 做不就完事了吗?: up down left right - use direction array 
        rows = len(grid)
        cols = len(grid[0])
        # general 的情况
        if k >= rows + cols - 2: return rows + cols -2
        q = collections.deque([])
        q.append((0,(0,0,k)))
        visited = set((0,0,k)) # visited 这里出了问题吗难道是
        dir = [(0,1),(0,-1),(1,0),(-1,0)]
        while q:
            move, (row, col, removals_left) = q.popleft()
            if row == rows -1 and col == cols -1: return move

            for dr, dc in dir:
                new_row = row + dr
                new_col = col + dc

                if ( new_row >= 0 and new_row < rows and new_col >=0 and new_col < cols):
                    new_removals = removals_left - grid[new_row][new_col]
                    if new_removals >= 0 and (new_row, new_col, new_removals) not in visited:
                        visited.add((new_row, new_col, new_removals))
                        q.append((move + 1, (new_row, new_col, new_removals)))
        return -1

# 犯错点:

1. 为什么不能够在 new_row, new_col 计算出来之后,直接计算new_removals,因为此时还没有对new_row和new_col的值进行判断,如果直接计算,函数会报错:index out of range

2. 在初始化queue和visited set的时候,queue存的是一个复合的tuple,(a,(b,c,d))格式,visited set存的是一个三元组, 即(a,b,c)格式

# 时间和空间复杂度分析:

We are essentially constructing a graph with n * m * k nodes. Each node can have at most 4 edges (to adjacent unblocked nodes at the same level and blocked nodes at the higher level).

Thus, our graph has |V| = O(n * m * k) vertices and |E| = O(n * m * k) edges.
Then, we simply run BFS to find the shortest path which takes O(|V| + |E|) = O(n * m * k) time.

其实还是没有很懂,为什么要乘以 K?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值