mirror of
https://gitlab.com/mfocko/LeetCode.git
synced 2024-11-10 00:09:06 +01:00
111 lines
3 KiB
C#
111 lines
3 KiB
C#
|
public class Solution {
|
||
|
private static readonly int WATER = 0;
|
||
|
private static readonly int ISLAND = 1;
|
||
|
|
||
|
private static readonly List<(int dy, int dx)> DIRECTIONS = [
|
||
|
(1, 0),
|
||
|
(-1, 0),
|
||
|
(0, 1),
|
||
|
(0, -1)
|
||
|
];
|
||
|
|
||
|
private static void RunBFS(int[][] grid, int y0, int x0, int mark) {
|
||
|
var q = new Queue<(int y, int x)>();
|
||
|
|
||
|
// Handle the start
|
||
|
grid[y0][x0] = mark;
|
||
|
q.Enqueue((y0, x0));
|
||
|
|
||
|
while (q.TryDequeue(out var next)) {
|
||
|
var (y, x) = next;
|
||
|
|
||
|
foreach (var (dy, dx) in DIRECTIONS) {
|
||
|
var nextY = y + dy;
|
||
|
var nextX = x + dx;
|
||
|
|
||
|
if (nextY < 0 || nextY >= grid.Length || nextX < 0 || nextX >= grid[nextY].Length) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (grid[nextY][nextX] != ISLAND) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
grid[nextY][nextX] = mark;
|
||
|
q.Enqueue((nextY, nextX));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void MarkIslands(int[][] grid) {
|
||
|
int mark = 1;
|
||
|
|
||
|
for (int y = 0; y < grid.Length; ++y) {
|
||
|
for (int x = 0; x < grid[y].Length; ++x) {
|
||
|
if (grid[y][x] == ISLAND) {
|
||
|
RunBFS(grid, y, x, ++mark);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool CheckSubIsland(int[][] grid1, int[][] grid2, int y0, int x0) {
|
||
|
if (grid1[y0][x0] == WATER || grid2[y0][x0] == WATER) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var q = new Queue<(int y, int x)>();
|
||
|
|
||
|
// Handle the start; sink the island to optimize for time complexity
|
||
|
var expectedMark = grid1[y0][x0];
|
||
|
grid2[y0][x0] = WATER;
|
||
|
q.Enqueue((y0, x0));
|
||
|
|
||
|
var isSubIsland = true;
|
||
|
while (q.TryDequeue(out var next)) {
|
||
|
var (y, x) = next;
|
||
|
|
||
|
foreach (var (dy, dx) in DIRECTIONS) {
|
||
|
var nextY = y + dy;
|
||
|
var nextX = x + dx;
|
||
|
|
||
|
// bounds
|
||
|
if (nextY < 0 || nextY >= grid2.Length || nextX < 0 || nextX >= grid2[nextY].Length) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// island continuation
|
||
|
if (grid2[nextY][nextX] != ISLAND) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// check if the mark matches
|
||
|
if (grid1[nextY][nextX] != expectedMark) {
|
||
|
isSubIsland = false;
|
||
|
}
|
||
|
|
||
|
// sink to optimize
|
||
|
grid2[nextY][nextX] = WATER;
|
||
|
q.Enqueue((nextY, nextX));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return isSubIsland;
|
||
|
}
|
||
|
|
||
|
public int CountSubIslands(int[][] grid1, int[][] grid2) {
|
||
|
MarkIslands(grid1);
|
||
|
|
||
|
int subislands = 0;
|
||
|
for (int y = 0; y < grid2.Length; ++y) {
|
||
|
for (int x = 0; x < grid2[y].Length; ++x) {
|
||
|
if (CheckSubIsland(grid1, grid2, y, x)) {
|
||
|
++subislands;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return subislands;
|
||
|
}
|
||
|
}
|