1- from typing import List
2- from collections import deque
1+ from typing import List , collections
32
4- class Solution :
5- def shortestPathBinaryMatrix (self , grid : List [List [int ]]) -> int :
6- size = len (grid ) - 1
7- if grid [0 ][0 ] == 1 or grid [size ][size ] == 1 : return - 1
8- if len (grid ) == 1 : return 1
3+ # 解法1: bfs. 直接修改输入 优化空间复杂度. T(m*n) S(n*n) 每个格子最多处理1次
4+ def shortestPathBinaryMatrix (grid : List [List [int ]]) -> int :
5+ size = len (grid ) - 1
6+ if grid [0 ][0 ] == 1 or grid [size ][size ] == 1 :
7+ return - 1
8+ if len (grid ) == 1 : # n * n 只有1个格子
9+ return 1
10+
11+ dx = [0 , 1 , 0 , - 1 , 1 , 1 , - 1 , - 1 ]
12+ dy = [1 , 0 , - 1 , 0 , 1 , - 1 , 1 , - 1 ]
13+ step = 0
14+ queue = collections .deque ([(0 ,0 )])
15+ grid [0 ][0 ] = 1 # 把走过的路变成obsticles 节省用visited
16+ while queue :
17+ step += 1 # 这里加step 之后不用加了
18+ for i in range (len (queue )):
19+ x , y = queue .popleft ()
20+ if x == size and y == size :
21+ return step
22+ for d in range (8 ):
23+ newx = x + dx [d ]
24+ newy = y + dy [d ]
25+ if 0 <= newx <= size and 0 <= newy <= size and grid [newx ][newy ] == 0 :
26+ queue .append ((newx , newy ))
27+ grid [newx ][newy ] = 1 # mark visited
28+ return - 1
929
10- queue , level = deque ([(0 ,0 )]), 2 # at least two cells: start and end cells
11- while queue :
12- for _ in range (len (queue )):
13- coord_y , coord_x = queue .popleft ()
14- for (dx ,dy ) in ((0 , - 1 ), (- 1 , - 1 ), (- 1 , 0 ), (- 1 , 1 ), (0 , 1 ), (1 , 1 ), (1 , 0 ), (1 , - 1 )):
15- nx , ny = coord_x + dx , coord_y + dy
16- if nx < 0 or ny < 0 or nx > size or ny > size or grid [ny ][nx ] != 0 : # filter out unfeasible cell
17- continue
18- if ny == size and nx == size : # find end cell
19- return level
20- grid [ny ][nx ] = 2 # act as a visted set
21- queue .append ((ny , nx )) # enqueue a feasible new cell
22- level += 1
23- return - 1
30+ # variant: return one shorest path.
31+ # bfs的过程中 用dict[(nx, ny)] = (x, y)表示从(x,y)走到的(nx,ny). 在终点back trace回去.
32+ def oneShortestPathBinaryMatrix (grid : List [List [int ]]) -> List [tuple [int ]]:
33+ size = len (grid ) - 1
34+ if grid [0 ][0 ] == 1 or grid [size ][size ] == 1 :
35+ return []
36+ if len (grid ) == 1 : # n * n 只有1个格子
37+ return [(0 , 0 )]
38+
39+ dx = [0 , 1 , 0 , - 1 , 1 , 1 , - 1 , - 1 ]
40+ dy = [1 , 0 , - 1 , 0 , 1 , - 1 , 1 , - 1 ]
41+ step = 0
42+ queue = collections .deque ([(0 ,0 )])
43+ trace = collections .defaultdict (tuple )
44+ grid [0 ][0 ] = 1 # 把走过的路变成obsticles 节省用visited
45+ while queue :
46+ step += 1 # 这里加step 之后不用加了
47+ for _ in range (len (queue )):
48+ x , y = queue .popleft ()
49+ if x == size and y == size :
50+ ret = collections .deque ()
51+ ret .appendleft ((x , y ))
52+ while (x , y ) != (0 ,0 ):
53+ (x , y ) = trace [(x , y )]
54+ ret .appendleft ((x , y ))
55+ return ret
56+ for d in range (8 ):
57+ newx = x + dx [d ]
58+ newy = y + dy [d ]
59+ if 0 <= newx <= size and 0 <= newy <= size and grid [newx ][newy ] == 0 :
60+ queue .append ((newx , newy ))
61+ trace [(newx , newy )] = (x , y )
62+ grid [newx ][newy ] = 1 # mark visited
63+ return []
64+
65+ # variant: return any one path, not necessary shorest.
66+ # 解法:DFS.
67+ def onePathBinaryMatrix (grid : List [List [int ]]) -> List [tuple [int ]]:
68+ if not grid or grid [0 ][0 ] != 0 or grid [len (grid ) - 1 ][len (grid [0 ]) - 1 ] != 0 :
69+ return - 1
70+ tmp = [(0 ,0 )]
71+ ret = []
72+ grid [0 ][0 ] = 1
73+ dfs (ret , tmp , grid , 0 , 0 )
74+ return ret
75+
76+ def dfs (ret , tmp , grid , x , y ):
77+ if len (ret ) > 0 : # 找到一个解
78+ return
79+ if x == len (grid ) - 1 and y == len (grid [0 ]) - 1 :
80+ ret .append (tmp [:]) # 这里要深拷贝
81+ return
82+
83+ dx = [0 , 1 , 0 , - 1 , 1 , 1 , - 1 , - 1 ]
84+ dy = [1 , 0 , - 1 , 0 , - 1 , 1 , 1 , - 1 ]
85+ for i in range (8 ):
86+ nx , ny = x + dx [i ], y + dy [i ]
87+ if 0 <= nx <= len (grid ) - 1 and 0 <= ny <= len (grid [0 ]) - 1 and grid [nx ][ny ] == 0 :
88+ grid [nx ][ny ] = 1 # mark visted
89+ tmp .append ((nx , ny )) # add trace
90+ dfs (ret , tmp , grid , nx , ny )
91+ tmp .pop () # restore status
92+ grid [nx ][ny ] = 0
93+
94+ grid0 = [[0 ,0 ,0 ],[1 ,1 ,0 ],[1 ,1 ,0 ]]
95+ grid1 = [[0 ,1 ],[1 ,0 ]]
96+ print (oneShortestPathBinaryMatrix (grid1 ))
0 commit comments