Skip to content

Commit 4689bc8

Browse files
committed
added problem 1970
1 parent 3441c28 commit 4689bc8

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

problems/problem1970/last_cross.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package problem1970
2+
3+
/*
4+
There is a 1-based binary matrix where 0 represents land and 1 represents water.
5+
You are given integers row and col representing the number of rows and columns in the matrix, respectively.
6+
Initially on day 0, the entire matrix is land. However, each day a new cell becomes flooded with water.
7+
You are given a 1-based 2D array cells, where cells[i] = [ri, ci] represents that
8+
on the ith day, the cell on the rith row and cith column (1-based coordinates) will be covered with water (i.e., changed to 1).
9+
You want to find the last day that it is possible to walk from the top to the bottom by only walking on land cells.
10+
You can start from any cell in the top row and end at any cell in the bottom row.
11+
You can only travel in the four cardinal directions (left, right, up, and down).
12+
Return the last day where it is possible to walk from the top to the bottom by only walking on land cells.
13+
*/
14+
15+
type Coord struct {
16+
X, Y int
17+
}
18+
19+
var Start = Coord{-1, -1}
20+
var End = Coord{-2, -2}
21+
22+
var Moves = [4][2]int{
23+
{1, 0}, {0, 1}, {-1, 0}, {0, -1},
24+
}
25+
26+
func latestDayToCross(row, col int, cells [][]int) int {
27+
var res int
28+
// swamp[x][y] is 1 if the cells is land, and 0 if water
29+
var swamp = make([][]int, row)
30+
// Start with everything as water
31+
for i := range swamp {
32+
swamp[i] = make([]int, col)
33+
}
34+
35+
// groups[coord] is the parent of coord in the disjoint set
36+
var groups = map[Coord]Coord{Start: Start, End: End}
37+
// Add the start and end to the group
38+
for i := 0; i < col; i++ {
39+
groups[Coord{0, i}] = Start
40+
groups[Coord{row - 1, i}] = End
41+
}
42+
43+
// Start adding land (instead of removing water)
44+
for res = len(cells) - 1; res >= 0; res-- {
45+
cx, cy := cells[res][0]-1, cells[res][1]-1
46+
// Mark current cells as land
47+
swamp[cx][cy] = 1
48+
for _, mov := range Moves {
49+
// Try to connect all adjacent land tiles
50+
nx, ny := cx+mov[0], cy+mov[1]
51+
if isInside(row, col, nx, ny) && swamp[nx][ny] == 1 {
52+
union(groups, Coord{cx, cy}, Coord{nx, ny})
53+
}
54+
}
55+
// If the parent of start is the parent of end, we are connected
56+
if find(groups, Start) == find(groups, End) {
57+
return res
58+
}
59+
}
60+
return res
61+
}
62+
63+
func isInside(row, col, x, y int) bool {
64+
return x >= 0 && x < row && y >= 0 && y < col
65+
}
66+
67+
func find(uf map[Coord]Coord, x Coord) Coord {
68+
if uf[x] == x {
69+
// If x is the parent of itself, it is the root of the group
70+
return uf[x]
71+
} else {
72+
// If x is not the parent of itself, we call this function again
73+
// to find the real parent, and update the map
74+
uf[x] = find(uf, uf[x])
75+
return uf[x]
76+
}
77+
}
78+
79+
func union(uf map[Coord]Coord, x, y Coord) {
80+
var rootx, rooty Coord
81+
if _, found := uf[x]; !found {
82+
// If this is the first time seeing x, set it as the root of it's group
83+
uf[x] = x
84+
}
85+
if _, found := uf[y]; !found {
86+
// If this is the first time seeing y, set it as the root of it's group
87+
uf[y] = y
88+
}
89+
// Finding the roots of x and y
90+
rootx = find(uf, x)
91+
rooty = find(uf, y)
92+
// Setting the root of rootx be rooty effectivly merging the groups
93+
uf[rootx] = rooty
94+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package problem1970
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
type TestCase struct {
11+
Row, Col int
12+
Cells [][]int
13+
Expected int
14+
}
15+
16+
var TestCases = []TestCase{
17+
{2, 2, [][]int{{1, 1}, {2, 1}, {1, 2}, {2, 2}}, 2},
18+
{2, 2, [][]int{{1, 1}, {1, 2}, {2, 1}, {2, 2}}, 1},
19+
{3, 3, [][]int{{1, 2}, {2, 1}, {3, 3}, {2, 2}, {1, 1}, {1, 3}, {2, 3}, {3, 2}, {3, 1}}, 3},
20+
}
21+
22+
func TestLastDayWeCanCross(t *testing.T) {
23+
assert := assert.New(t)
24+
25+
for _, tc := range TestCases {
26+
want := tc.Expected
27+
got := latestDayToCross(tc.Row, tc.Col, tc.Cells)
28+
assert.Equal(want, got, fmt.Sprintf("%+v", tc))
29+
}
30+
}
31+
32+
func BenchmarkLastDayWeCanCross(b *testing.B) {
33+
for i := 0; i < b.N; i++ {
34+
for _, tc := range TestCases {
35+
latestDayToCross(tc.Row, tc.Col, tc.Cells)
36+
}
37+
}
38+
}

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ Each problem is in it's own directory, with test files. There are helper package
476476
| 1926 | [Nearest Exit from Entrance in Maze](https://leetcode.com/problems/nearest-exit-from-entrance-in-maze) | [My Solution](./problems/problem1926) ||
477477
| 1962 | [Remove Stones to Minimize the Total](https://leetcode.com/problems/remove-stones-to-minimize-the-total) | [My Solution](./problems/problem1962) ||
478478
| 1964 | [Find the Longest Valid Obstacle Course at Each Position](https://leetcode.com/problems/find-the-longest-valid-obstacle-course-at-each-position) | [My Solution](./problems/problem1964) ||
479+
| 1970 | [Last Day Where You Can Still Cross](https://leetcode.com/problems/last-day-where-you-can-still-cross) | [My Solution](./problems/problem1970) ||
479480
| 1971 | [Find if Path Exists in Graph](https://leetcode.com/problems/find-if-path-exists-in-graph) | [My Solution](./problems/problem1971) ||
480481
| 1996 | [The Number of Weak Characters in the Game](https://leetcode.com/problems/the-number-of-weak-characters-in-the-game) | [My Solution](./problems/problem1996) ||
481482
| 2000 | [Reverse Prefix of Word](https://leetcode.com/problems/reverse-prefix-of-word/) | [My Solution](./problems/problem2000) ||

0 commit comments

Comments
 (0)