leetcode

Leetcode Solutions (0x6A73)
git clone https://git.pngu.org/leetcode
Log | Files | Refs | Submodules | README

commit d3c844ce2aef16dbc9fe26fce617f68a1cb1a2a4
parent dac10095fd54f29edb2e262a408a515de725a0e8
Author: Jack Sangdahl <jack@pngu.org>
Date:   Tue, 30 Dec 2025 22:30:34 -0700

1970. last day where you can still cross

Diffstat:
Alast_day_where_you_can_cross.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alast_day_where_you_can_cross.py | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 180 insertions(+), 0 deletions(-)

diff --git a/last_day_where_you_can_cross.c b/last_day_where_you_can_cross.c @@ -0,0 +1,93 @@ +// 1970. Last Day Where You Can Still Cross +#include "leetcode.h" + +/* + * there is a 1-based binary matrix where '0' represents land and '1' represents + * water. you are given integers 'row' and 'col' representing the number of rows + * and columns in the matrix, repsectively. initially, on day 0, the entier + * matrix is land. however, each day a new cell becomes flooded with water. you + * are given a 1-based 2d array 'cells' where 'cells[i] = [ri, ci]' represents + * that on the i'th day, the cell on the ri'th row and the ci'th column will be + * covered with water. you want to find the last day that it is still possible + * to walk from the top to the bottom only by walking on land cells. you can + * start rom any cell in the top row and end at any cell in the bottom row. you + * can only travel in the four cardinal directions. + */ + +int find(int *p, int x) { + if (p[x] != x) + p[x] = find(p, p[x]); + return p[x]; +} + +void unite(int *p, int *r, int a, int b) { + a = find(p, a); + b = find(p, b); + if (a == b) + return; + if (r[a] < r[b]) + p[a] = b; + else if (r[a] > r[b]) + p[b] = a; + else + p[b] = a, r[a]++; +} + +int latestDayToCross(int row, int col, int **cells, int cellsSize, + int *cellsColSize) { + int n = row * col, top = n, bottom = n + 1, ans = 0; + int *parent = (int *)malloc((n + 2) * sizeof(int)); + int *rank = (int *)calloc(n + 2, sizeof(int)); + bool *land = (bool *)calloc(n, sizeof(bool)); + int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; + for (int i = 0; i < n + 2; i++) + parent[i] = i; + for (int d = cellsSize - 1; d >= 0; d--) { + int r = cells[d][0] - 1; + int c = cells[d][1] - 1; + int id = r * col + c; + land[id] = true; + for (int i = 0; i < 4; i++) { + int nr = r + dir[i][0], nc = c + dir[i][1]; + if (nr >= 0 && nc >= 0 && nr < row && nc < col) { + int nid = nr * col + nc; + if (land[nid]) + unite(parent, rank, id, nid); + } + } + if (r == 0) + unite(parent, rank, id, top); + if (r == row - 1) + unite(parent, rank, id, bottom); + if (find(parent, top) == find(parent, bottom)) { + ans = d; + break; + } + } + free(parent); + free(rank); + free(land); + return ans; +} + +int main() { + int c1i[4][2] = {{1, 1}, {2, 1}, {1, 2}, {2, 2}}; + int c2i[4][2] = {{1, 1}, {1, 2}, {2, 1}, {2, 2}}; + int c3i[9][2] = {{1, 2}, {2, 1}, {3, 3}, {2, 2}, {1, 1}, + {1, 3}, {2, 3}, {3, 2}, {3, 1}}; + struct two_d_arr *c1 = + two_d_arr_init(ARRAY_SIZE(c1i), ARRAY_SIZE(c1i[0]), c1i); + struct two_d_arr *c2 = + two_d_arr_init(ARRAY_SIZE(c2i), ARRAY_SIZE(c2i[0]), c2i); + struct two_d_arr *c3 = + two_d_arr_init(ARRAY_SIZE(c3i), ARRAY_SIZE(c3i[0]), c3i); + printf("%d\n", latestDayToCross(2, 2, c1->arr, c1->row_size, + c1->col_size)); // expect: 2 + printf("%d\n", latestDayToCross(2, 2, c2->arr, c2->row_size, + c2->col_size)); // expect: 1 + printf("%d\n", latestDayToCross(3, 3, c3->arr, c3->row_size, + c3->col_size)); // expect: 3 + two_d_arr_free(c1); + two_d_arr_free(c2); + two_d_arr_free(c3); +} diff --git a/last_day_where_you_can_cross.py b/last_day_where_you_can_cross.py @@ -0,0 +1,87 @@ +# 1970. Last Day Where You Can Still Cross + +""" +there is a 1-based binary matrix where '0' represents land and '1' represents +water. you are given integers 'row' and 'col' representing the number of rows +and columns in the matrix, repsectively. initially, on day 0, the entier +matrix is land. however, each day a new cell becomes flooded with water. you +are given a 1-based 2d array 'cells' where 'cells[i] = [ri, ci]' represents +that on the i'th day, the cell on the ri'th row and the ci'th column will be +covered with water. you want to find the last day that it is still possible +to walk from the top to the bottom only by walking on land cells. you can +start rom any cell in the top row and end at any cell in the bottom row. you +can only travel in the four cardinal directions. +""" + + +class Solution(object): + def latestDayToCross(self, row, col, cells): + """ + :type row: int + :type col: int + :type cells: List[List[int]] + :rtype: int + """ + n = row * col + top, bottom = n, n + 1 + parent = list(range(n + 2)) + rank = [0] * (n + 2) + land = [False] * n + + def find(x): + if parent[x] != x: + parent[x] = find(parent[x]) + return parent[x] + + def union(a, b): + a, b = find(a), find(b) + if a == b: + return + if rank[a] < rank[b]: + parent[a] = b + elif rank[a] > rank[b]: + parent[b] = a + else: + parent[b] = a + rank[a] += 1 + + for d in range(len(cells) - 1, -1, -1): + r, c = cells[d][0] - 1, cells[d][1] - 1 + idx = r * col + c + land[idx] = True + for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)): + nr, nc = r + dr, c + dc + if 0 <= nr < row and 0 <= nc < col: + nid = nr * col + nc + if land[nid]: + union(idx, nid) + if r == 0: + union(idx, top) + if r == row - 1: + union(idx, bottom) + if find(top) == find(bottom): + return d + return 0 + + +if __name__ == "__main__": + obj = Solution() + print(obj.latestDayToCross(row=2, col=2, cells=[[1, 1], [2, 1], [1, 2], [2, 2]])) + print(obj.latestDayToCross(row=2, col=2, cells=[[1, 1], [1, 2], [2, 1], [2, 2]])) + print( + obj.latestDayToCross( + row=3, + col=3, + cells=[ + [1, 2], + [2, 1], + [3, 3], + [2, 2], + [1, 1], + [1, 3], + [2, 3], + [3, 2], + [3, 1], + ], + ) + )