Skip to content

Commit 9c26c30

Browse files
author
Albert Hu
authored
Merge pull request #14 from alberthu16/day19
Day 19: distances from 0s in a matrix (BFS)
2 parents 96f413a + 6424ebb commit 9c26c30

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed

day19/README.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
question of the day: https://leetcode.com/problems/01-matrix/#/description
2+
3+
Given a matrix consists of 0 and 1, find the distance of
4+
the nearest 0 for each cell.
5+
6+
The distance between two adjacent cells is 1.
7+
8+
*Example 1:*
9+
10+
Input:
11+
12+
```ruby
13+
0 0 0
14+
0 1 0
15+
0 0 0
16+
```
17+
18+
Output:
19+
20+
```ruby
21+
0 0 0
22+
0 1 0
23+
0 0 0
24+
```
25+
26+
*Example 2:*
27+
28+
Input:
29+
30+
```ruby
31+
0 0 0
32+
0 1 0
33+
1 1 1
34+
```
35+
36+
Output:
37+
38+
```ruby
39+
0 0 0
40+
0 1 0
41+
1 2 1
42+
```
43+
44+
Assumptions we can make:
45+
46+
1. The number of elements of the given matrix will not exceed 10,000.
47+
2. There are at least one 0 in the given matrix.
48+
3. The cells are adjacent in only four directions: up, down, left and right.
49+
50+
## Ideas
51+
52+
This is like drawing out a contour map. The 0's are the peaks of
53+
hills and mountains, while the parts of the matrix that are far away
54+
from any 0's are like the valleys.
55+
56+
We can start from each peak and go outwards. It'd be a BFS-like
57+
approach. Do a search through the whole matrix once first and find
58+
where all the 0's are. Add each of those positions into a queue,
59+
and then use that queue to start off a BFS. During this BFS, we
60+
check the neighboring cells to see what the minimal value is that
61+
we can place in this cell.
62+
63+
This solution is `O(n)` to find the 0s, and then `O(n)` to run the
64+
BFS. My implementation also requires `O(n)` space, although I think
65+
it's possible to modify the matrix in-place with some more clever
66+
checking.
67+
68+
## Code
69+
70+
[Ruby](./matrixCountours.rb)
71+
72+
## Follow up

day19/matrixCountours.rb

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
def contourDistances(matrix)
2+
rows, cols = matrix.size, matrix[0].size
3+
4+
if rows == 0 || cols == 0
5+
return matrix
6+
end
7+
8+
contours = Array.new(rows).map { |x| [nil] * cols }
9+
queue = []
10+
# start by finding 0s
11+
for row in 0..rows-1
12+
for col in 0..cols-1
13+
if matrix[row][col] == 0
14+
queue << [row, col]
15+
contours[row][col] = 0
16+
end
17+
end
18+
end
19+
20+
# do bfs
21+
while queue.size > 0
22+
current = queue.shift
23+
row, col = current
24+
contours[row][col] = getMinNeighbor(contours, row, col) + 1
25+
for i, j in [[row-1, col], [row, col-1], [row, col+1], [row+1, col]]
26+
if withinBounds([i, j], rows, cols) && contours[i][j] == nil
27+
queue << [i, j]
28+
end
29+
end
30+
end
31+
32+
contours
33+
end
34+
35+
def withinBounds(coordinate, rows, cols)
36+
x, y = coordinate
37+
x >= 0 && x < rows && y >= 0 && y < cols
38+
end
39+
40+
def getMinNeighbor(matrix, row, col)
41+
if matrix[row][col] == 0
42+
return -1
43+
end
44+
45+
vals = []
46+
rows, cols = matrix.size, matrix[0].size
47+
for i, j in [[row-1, col], [row, col-1], [row, col+1], [row+1, col]]
48+
if withinBounds([i, j], rows, cols)
49+
if matrix[i][j] != nil
50+
vals << matrix[i][j]
51+
end
52+
end
53+
end
54+
55+
vals.min
56+
end
57+
58+
#########
59+
# Tests #
60+
#########
61+
62+
class AssertionError < RuntimeError
63+
end
64+
65+
def assert &block
66+
raise AssertionError unless yield
67+
end
68+
69+
def tests
70+
# edge cases
71+
empty = [[]]
72+
emptyOutput = [[]]
73+
assert { contourDistances(empty) == emptyOutput }
74+
75+
one = [[0]]
76+
oneOutput = [[0]]
77+
assert { contourDistances(one) == oneOutput }
78+
79+
# other cases
80+
matrix = [[1,1,1],
81+
[1,0,1],
82+
[1,1,1]]
83+
84+
output = [[2,1,2],
85+
[1,0,1],
86+
[2,1,2]]
87+
assert { contourDistances(matrix) == output }
88+
89+
matrix1 = [[0,0,0],
90+
[0,1,0],
91+
[0,0,0]]
92+
93+
output1 = [[0,0,0],
94+
[0,1,0],
95+
[0,0,0]]
96+
assert { contourDistances(matrix1) == output1 }
97+
98+
matrix2 = [[0,0,0],
99+
[0,1,0],
100+
[1,1,1]]
101+
102+
output2 = [[0,0,0],
103+
[0,1,0],
104+
[1,2,1]]
105+
assert { contourDistances(matrix2) == output2 }
106+
end
107+
108+
tests()

0 commit comments

Comments
 (0)