[LeetCode] 490. The Maze 迷宫
一:题意
链接:https://leetcode.com/articles/the-maze/
给定一个二维平面表示一个迷宫,迷宫中0代表空闲处,1代表墙,有一个人从start处可以上下左右四个方向移动(得朝着一个方向一直走到头,碰到墙才能换方向),碰到墙得换方向移动,问是否停在目的地destination。
经过目的地不算到达,球并不会停下来
边界已经用墙封住了,图中显示出了!
二:思路
- dfs是不行的,超时了!
- 使用bfs来做
1:首先从start开始,作为起始节点
2:扩展相邻结点,把上下左右四个方向走到尽头的坐标加入队列中
3:直到遍历结束
三:实现
class Solution(object):
def hasPath(self, maze, start, destination):
if not maze: return False
if start == destination: return True
vis = set()
m, n = len(maze), len(maze[0])
dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)] # 四个方向
queue = [(start[0], start[1])] # 记录的是四个方向的尽头的坐标
vis.add((start[0], start[1]))
while queue:
i, j = queue.pop()
if i == destination[0] and j == destination[1]:
return True
for dis in dirs: # 四个方向
x = i + dis[0]
y = j + dis[1]
while 0 <= x < m and n <= y < n and maze[x][y] == 0: # 一直往一个方向走,直到撞墙
x += dis[0]
y += dis[1]
# 要退一步,上一行的while循环多走了一步到墙里面了!
x = x - dir[0]
y = y - dir[1]
# 到达尽头后,查看是否访问过
if (x, y) not in vis:
vis.add((x, y))
queue = [(x, y)] + queue # 先进先出为队列,BFS
return False
[LeetCode] 505. The Maze II 迷宫之二
一:题意
地址:https://leetcode.com/articles/the-maze-ii/
题意与上一题一样,只是结果不是返回是否可到达目的地,而是到达目的地经历最短的路径。不存在路径返回-1
二:思路
- dfs
- bfs
广度优先搜索,和上一题写法类似,只是记录一下到达坐标(x,y)的路径距离,而且不需要去重了(不需要vis=set()了),因为需要遍历多条路径。
distance[i][j] 代表从开始位置到坐标 (i,j)的最短距离
更新最短距离:if distance[i][j] + count < distance[x][y] - Dijkstra Algorithm
三:实现
- dfs
class Solution(object):
def shortestDistance(self, maze, start, destination):
# 经过目的地不算,必须停留在目的地才行
if not maze: return -1
if start == destination: return 0
distance = [[float('inf')]*n for i in range(m)] # distance[i][j] 代表从开始位置到坐标 (i,j)的最短距离
distance[start[0]][start[1]] = 0
self.dfs(maze, start, distance)
return distance[destination[0]][destination[1]] if distance[destination[0]][destination[1]] != float('inf') else -1
def dfs(self, maze, start, distance):
m, n = len(maze), len(maze[0])
dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)] # 四个方向
for dis in dirs:
x = start[0] + dis[0]
y = start[0] + dis[1]
count = 0
while 0 <= x < n and 0 <= y < m and maze[x][y] == 0:
count += 1
x += dis[0]
y += dis[1]
# 多走了一步啊,其实可以在while循坏中控制少走一步,改成maze[x+dis[0]][y+dis[1]] == 0就行
count -= 1
x = x - dir[0]
y = y - dir[1]
if distance[i][j] + count < distance[x][y]: # 更新最短距离
distance[x][y] = distance[i][j] + count
self.dfs(maze, [x, y], distance)
- bfs
class Solution(object):
def shortestDistance(self, maze, start, destination):
# 经过目的地不算,必须停留在目的地才行
if not maze: return -1
if start == destination: return 0
m, n = len(maze), len(maze[0])
distance = [[float('inf')]*n for i in range(m)] # distance[i][j] 代表从开始位置到坐标 (i,j)的最短距离
distance[start[0]][start[1]] = 0
dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)] # 四个方向
queue = [(start[0], start[1])] # 记录的是四个方向的尽头的坐标
while queue:
i, j = queue.pop()
for dis in dirs:
count = 0
x = i + dis[0]
y = j + dis[1]
while 0 <= x < n and 0 <= y < m and maze[x][y] == 0:
count += 1
x += dis[0]
y += dis[1]
# 多走了一步啊,其实可以在while循坏中控制少走一步,改成maze[x+dis[0]][y+dis[1]] == 0就行
count -= 1
x = x - dir[0]
y = y - dir[1]
if distance[i][j] + count < distance[x][y]: # 更新最短距离
queue = [(x, y)] + queue
distance[x][y] = distance[i][j] + count
return distance[destination[0]][destination[1]] if distance[destination[0]][destination[1]] != float('inf') else -1
[LeetCode] 499 The Maze III 迷宫之三
一:题意
在路径中间放了个陷阱,让球在最小步数内滚到陷阱之中,此时返回的并不是最小步数,而是滚动的方向,用u, r, d, l 这四个字母来分别表示上右下左,而且在步数相等的情况下,让我们返回按字母排序小的答案。
这题只要经过陷阱就行,而不是停留在陷阱处。