目录
🍕题目
🍔思路
由题目我们可以知道每分钟每个腐烂的橘子都会使上下左右相邻的新鲜橘子腐烂,这其实是一个模拟广度优先搜索的过程。
观察到对于所有的腐烂橘子,其实它们在广度优先搜索上是等价于同一层的节点的。
有一个腐烂橘子(我们令其为超级源点)会在下一秒把这些橘子都变腐烂,而这个腐烂橘子刚开始在的时间是 -1 ,那么按照广度优先搜索的算法,下一分钟也就是第 0分钟的时候,这个腐烂橘子会把它们都变成腐烂橘子,然后继续向外拓展。
那么在广度优先搜索的时候,我们将这些腐烂橘子都放进队列里进行广度优先搜索即可,最后每个新鲜橘子被腐烂的最短时间 dis[x][y]其实是以这个超级源点的腐烂橘子为起点的广度优先搜索得到的结果。
注意:
为了确认是否所有新鲜橘子都被腐烂,可以记录一个变量 cnt表示当前网格中的新鲜橘子数,广度优先搜索的时候如果有新鲜橘子被腐烂,则 cnt -= 1 ,
最后搜索结束时如果 cnt 大于 0 ,说明有新鲜橘子没被腐烂,返回 -1 ,
否则返回所有新鲜橘子被腐烂的时间的最大值即可
多源广度优先搜索
🍟详细见代码
class Solution:
def orangesRotting(grid):
M = len(grid)
N = len(grid[0])
queue = []
count = 0 # count 表示新鲜橘子的数量
for r in range(M):
for c in range(N):
if grid[r][c] == 1:
count += 1
elif grid[r][c] == 2:
queue.append((r, c))
round = 0 # round 表示腐烂的轮数,或者分钟数
while count > 0 and len(queue) > 0: # 还有好橘子且队列还有坏橘子
round += 1 # 层数+1
n = len(queue) # 记录这一层的坏橘子数
for i in range(n): # 遍历完这一层的坏橘子
r, c = queue.pop(0) # 取出队列开头的坏橘子坐标
if r-1 >= 0 and grid[r-1][c] == 1: # 右邻有好橘子
grid[r-1][c] = 2 # 好橘子变坏
count -= 1 # 好橘子数-1
queue.append((r-1, c)) # 新变坏的这只橘子进入坏橘子队列
if r+1 < M and grid[r+1][c] == 1: # 左邻有好橘子
grid[r+1][c] = 2
count -= 1
queue.append((r+1, c))
if c-1 >= 0 and grid[r][c-1] == 1: # 下邻有好橘子
grid[r][c-1] = 2
count -= 1
queue.append((r, c-1))
if c+1 < N and grid[r][c+1] == 1: # 上邻有好橘子
grid[r][c+1] = 2
count -= 1
queue.append((r, c+1))
if count > 0: # 还有好橘子
return -1
else: # 没有好橘子了
return round
🍕题目
其实处理的方法很简单:我们在进行广度优先搜索的时候会使用到队列,
在只有一个 0 的时候,我们在搜索前会把这个 0 的位置加入队列,才能开始进行搜索;
如果有多个 0,我们只需要把这些 0的位置都加入队列就行了。(然后套用模板)
通过0找1
🍔广度优先搜索
class Solution:
def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
m, n = len(matrix), len(matrix[0])
dist = [[0] * n for _ in range(m)]
zeroes_pos = [(i, j) for i in range(m) for j in range(n) if matrix[i][j] == 0]
# 将所有的 0 添加进初始队列中
q = collections.deque(zeroes_pos)
seen = set(zeroes_pos)
# 广度优先搜索
while q:
i, j = q.popleft()
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in seen:
dist[ni][nj] = dist[i][j] + 1
q.append((ni, nj))
seen.add((ni, nj))
return dist