Skip to content

Commit 6ae2e49

Browse files
committed
Shortest path in binary matrix
1 parent d9196e4 commit 6ae2e49

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# 1091. Shortest path in binary matrix
2+
# Topics: 'Array', 'Matrix', 'Breadth-First Search'
3+
# Level: 'Medium'
4+
5+
# Given an n x n binary matrix grid, return the length of the shortest clear path in the matrix. If there is no clear path, return -1.
6+
7+
# A clear path in a binary matrix is a path from the top-left cell (i.e., (0, 0)) to the bottom-right cell (i.e., (n - 1, n - 1)) such that:
8+
9+
# All the visited cells of the path are 0.
10+
# All the adjacent cells of the path are 8-directionally connected (i.e., they are different and they share an edge or a corner).
11+
12+
# The length of a clear path is the number of visited cells of this path.
13+
14+
15+
16+
# Example 1:
17+
18+
# Input: grid = [[0,1],[1,0]]
19+
# Output: 2
20+
21+
# Example 2:
22+
23+
# Input: grid = [[0,0,0],[1,1,0],[1,1,0]]
24+
# Output: 4
25+
26+
# Example 3:
27+
28+
# Input: grid = [[1,0,0],[1,1,0],[1,1,0]]
29+
# Output: -1
30+
31+
32+
33+
# Constraints:
34+
35+
# n == grid.length
36+
# n == grid[i].length
37+
# 1 <= n <= 100
38+
# grid[i][j] is 0 or 1
39+
40+
from collections import deque
41+
from typing import List
42+
43+
class Solution:
44+
def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
45+
ROWS, COLS = len(grid), len(grid[0])
46+
if grid[0][0] == 1:
47+
return -1
48+
length = 1
49+
visit = set()
50+
q = deque()
51+
q.append((0,0))
52+
visit.add((0,0))
53+
54+
while q:
55+
for i in range (len(q)):
56+
row, col = q.popleft()
57+
if row == ROWS-1 and col == COLS-1:
58+
return length
59+
directions = [
60+
# diagonals
61+
[-1,-1], [-1, 1], [1, -1], [1, 1],
62+
# straight
63+
[0, 1], [0, -1], [1, 0], [-1, 0]
64+
]
65+
for dr, dc in directions:
66+
if min(row + dr, col+dc) < 0:
67+
continue
68+
if row + dr == ROWS or col + dc == COLS:
69+
continue
70+
if (row+dr, col+dc) in visit:
71+
continue
72+
if grid[row+dr][col+dc] == 1:
73+
continue
74+
visit.add((row+dr,col+dc))
75+
q.append((row+dr, col+dc))
76+
length+=1
77+
return -1
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from collections import deque
2+
from typing import List
3+
from path import Solution
4+
5+
class Solution:
6+
def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
7+
ROWS, COLS = len(grid), len(grid[0])
8+
if grid[0][0] == 1:
9+
return -1
10+
length = 1
11+
visit = set()
12+
q = deque()
13+
q.append((0,0))
14+
visit.add((0,0))
15+
16+
while q:
17+
for i in range(len(q)):
18+
row, col = q.popleft()
19+
if row == ROWS-1 and col == COLS-1:
20+
return length
21+
directions = [
22+
# diagonals
23+
[-1,-1], [-1, 1], [1, -1], [1, 1],
24+
# straight
25+
[0, 1], [0, -1], [1, 0], [-1, 0]
26+
]
27+
for dr, dc in directions:
28+
if min(row + dr, col+dc) < 0:
29+
continue
30+
if row + dr == ROWS or col + dc == COLS:
31+
continue
32+
if (row+dr, col+dc) in visit:
33+
continue
34+
if grid[row+dr][col+dc] == 1:
35+
continue
36+
visit.add((row+dr,col+dc))
37+
q.append((row+dr, col+dc))
38+
length+=1
39+
return -1
40+
41+
42+
def test_shortest_path():
43+
solution = Solution()
44+
45+
# Test 1: Example 1 from problem - 2x2 grid
46+
grid1 = [[0,1],
47+
[1,0]]
48+
assert solution.shortestPathBinaryMatrix(grid1) == 2, "Test 1 Failed"
49+
print("✓ Test 1 passed: Example 1 - 2x2 grid")
50+
51+
# Test 2: Example 2 from problem - 3x3 grid
52+
grid2 = [[0,0,0],
53+
[1,1,0],
54+
[1,1,0]]
55+
assert solution.shortestPathBinaryMatrix(grid2) == 4, "Test 2 Failed"
56+
print("✓ Test 2 passed: Example 2 - 3x3 grid with path")
57+
58+
# Test 3: Example 3 from problem - no path (starting cell blocked)
59+
grid3 = [[1,0,0],
60+
[1,1,0],
61+
[1,1,0]]
62+
assert solution.shortestPathBinaryMatrix(grid3) == -1, "Test 3 Failed"
63+
print("✓ Test 3 passed: Example 3 - starting cell blocked")
64+
65+
# Test 4: Direct diagonal path
66+
grid4 = [[0,0,0],
67+
[0,0,0],
68+
[0,0,0]]
69+
assert solution.shortestPathBinaryMatrix(grid4) == 3, "Test 4 Failed"
70+
print("✓ Test 4 passed: Direct diagonal path")
71+
72+
# Test 5: Ending cell blocked
73+
grid5 = [[0,0,0],
74+
[0,0,0],
75+
[0,0,1]]
76+
assert solution.shortestPathBinaryMatrix(grid5) == -1, "Test 5 Failed"
77+
print("✓ Test 5 passed: Ending cell blocked")
78+
79+
# Test 6: No path exists (wall in middle)
80+
grid6 = [[0,0,1],
81+
[1,1,1],
82+
[1,0,0]]
83+
assert solution.shortestPathBinaryMatrix(grid6) == -1, "Test 6 Failed"
84+
print("✓ Test 6 passed: No path exists")
85+
86+
# Test 7: Single cell (edge case)
87+
grid7 = [[0]]
88+
assert solution.shortestPathBinaryMatrix(grid7) == 1, "Test 7 Failed"
89+
print("✓ Test 7 passed: Single cell grid")
90+
91+
# Test 8: Single cell blocked
92+
grid8 = [[1]]
93+
assert solution.shortestPathBinaryMatrix(grid8) == -1, "Test 8 Failed"
94+
print("✓ Test 8 passed: Single cell blocked")
95+
96+
# Test 9: Longer path needed
97+
grid9 = [[0,0,0,0],
98+
[1,1,1,0],
99+
[0,0,0,0],
100+
[0,1,1,0]]
101+
result9 = solution.shortestPathBinaryMatrix(grid9)
102+
assert result9 == 6, f"Test 9 Failed: Expected 5, got {result9}"
103+
print("✓ Test 9 passed: Longer path with obstacles")
104+
105+
106+
print("\n✅ All tests passed!")
107+
108+
if __name__ == "__main__":
109+
test_shortest_path()

0 commit comments

Comments
 (0)