From 4856bc8f3e9738806e590aa60c72f1fe6ccb014d Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Wed, 28 Aug 2024 23:37:45 +0200 Subject: [PATCH] =?UTF-8?q?cs:=20add=20=C2=AB1905.=20Count=20Sub=20Islands?= =?UTF-8?q?=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Focko --- cs/count-sub-islands.cs | 110 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 cs/count-sub-islands.cs diff --git a/cs/count-sub-islands.cs b/cs/count-sub-islands.cs new file mode 100644 index 0000000..2c14506 --- /dev/null +++ b/cs/count-sub-islands.cs @@ -0,0 +1,110 @@ +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; + } +}