Number of Islands BFS and DFS in DSA C# - Time & Space Complexity
We want to understand how the time needed to find islands grows as the map size grows.
How does the search through the grid change when the grid gets bigger?
Analyze the time complexity of the following code snippet.
public int NumIslands(char[][] grid) {
int count = 0;
for (int i = 0; i < grid.Length; i++) {
for (int j = 0; j < grid[0].Length; j++) {
if (grid[i][j] == '1') {
DFS(grid, i, j);
count++;
}
}
}
return count;
}
private void DFS(char[][] grid, int i, int j) {
if (i < 0 || j < 0 || i >= grid.Length || j >= grid[0].Length || grid[i][j] == '0') return;
grid[i][j] = '0';
DFS(grid, i + 1, j);
DFS(grid, i - 1, j);
DFS(grid, i, j + 1);
DFS(grid, i, j - 1);
}
This code counts islands by scanning the grid and using DFS to mark connected land.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each cell once during DFS or the main loops.
- How many times: Each cell is visited at most once in DFS and once in the nested loops.
As the grid size grows, the number of cells grows with rows times columns.
| Input Size (n x m) | Approx. Operations |
|---|---|
| 10 x 10 | About 100 visits |
| 100 x 100 | About 10,000 visits |
| 1000 x 1000 | About 1,000,000 visits |
Pattern observation: The operations grow roughly proportional to the total number of cells.
Time Complexity: O(n * m)
This means the time grows linearly with the total number of cells in the grid.
[X] Wrong: "DFS runs multiple times on the same cells, so time is more than O(n*m)."
[OK] Correct: Each cell is marked visited (turned to '0') so DFS never visits the same cell twice.
Understanding this helps you explain how graph traversal works on grids, a common interview skill.
"What if we used BFS instead of DFS? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem statement
The problem asks to count distinct islands, where islands are groups of connected '1's (land) in the grid.Step 2: Identify what is being counted
We count how many separate groups of connected land cells exist, not their size or perimeter.Final Answer:
Count how many groups of connected '1's (land) exist -> Option DQuick Check:
Number of islands = count of connected land groups [OK]
- Confusing island count with island size
- Counting water cells instead of land
- Ignoring connectivity rules (horizontal and vertical)
Solution
Step 1: Understand C# 2D array initialization
In C#, jagged arrays (array of arrays) are declared as char[][] and initialized with new char[][] and inner arrays. Number of Islands uses jagged arrays for grid[r][c] access and grid[0].Length.Step 2: Check each option's syntax
char[][] grid = new char[][] { new char[] {'1','0'}, new char[] {'0','1'} };: char[][] grid = new char[][] { new char[] {'1','0'}, new char[] {'0','1'} }; correctly uses jagged array syntax.
char[,] grid = new char[][] { {'1','0'}, {'0','1'} };: declares char[,] (rectangular) but tries jagged init - type mismatch.
char[,] grid = { {'1','0'}, {'0','1'} };: valid rectangular char[,], but incompatible with grid[r][c] and grid[0].Length.
char[][] grid = new char[2][2] { {'1','0'}, {'0','1'} };: new char[2][2] invalid syntax (incorrect brackets).Final Answer:
char[][] grid = new char[][] { new char[] {'1','0'}, new char[] {'0','1'} }; -> Option CQuick Check:
Jagged array with new keyword = correct syntax [OK]
- Omitting 'new' keyword in array initialization
- Confusing jagged arrays with rectangular arrays
- Using wrong braces or missing inner arrays
char[][] grid = new char[][] {
new char[] {'1','1','0','0'},
new char[] {'1','0','0','1'},
new char[] {'0','0','1','1'},
new char[] {'0','0','0','0'}
};
int CountIslands(char[][] grid) {
int count = 0;
int rows = grid.Length;
int cols = grid[0].Length;
bool[][] visited = new bool[rows][];
for (int i = 0; i < rows; i++) visited[i] = new bool[cols];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (grid[r][c] == '1' && !visited[r][c]) {
BFS(r, c, grid, visited);
count++;
}
}
}
return count;
}
void BFS(int r, int c, char[][] grid, bool[][] visited) {
int[] dr = { -1, 1, 0, 0 };
int[] dc = { 0, 0, -1, 1 };
Queue<(int, int)> queue = new Queue<(int, int)>();
queue.Enqueue((r, c));
visited[r][c] = true;
while (queue.Count > 0) {
var (row, col) = queue.Dequeue();
for (int i = 0; i < 4; i++) {
int nr = row + dr[i];
int nc = col + dc[i];
if (nr >= 0 && nr < grid.Length && nc >= 0 && nc < grid[0].Length && grid[nr][nc] == '1' && !visited[nr][nc]) {
queue.Enqueue((nr, nc));
visited[nr][nc] = true;
}
}
}
}
Console.WriteLine(CountIslands(grid));Solution
Step 1: Analyze the grid for connected islands
Islands are groups of '1's connected horizontally or vertically. The grid has these islands:
- Island 1: (0,0),(0,1),(1,0)
- Island 2: (1,3)
- Island 3: (2,2),(2,3)Step 2: BFS visits each island once
The BFS marks all connected '1's as visited. Each BFS call increments count by 1. Total BFS calls = number of islands = 3.Final Answer:
3 -> Option AQuick Check:
Count islands by BFS calls = 3 [OK]
- Counting diagonally connected '1's as one island
- Missing isolated single '1's as islands
- Not marking visited cells properly
void DFS(int r, int c, char[][] grid, bool[][] visited) {
if (r < 0 || r >= grid.Length || c < 0 || c >= grid[0].Length || grid[r][c] == '0')
return;
visited[r][c] = true;
DFS(r - 1, c, grid, visited);
DFS(r + 1, c, grid, visited);
DFS(r, c - 1, grid, visited);
DFS(r, c + 1, grid, visited);
}
int CountIslands(char[][] grid) {
int count = 0;
int rows = grid.Length;
int cols = grid[0].Length;
bool[][] visited = new bool[rows][];
for (int i = 0; i < rows; i++) visited[i] = new bool[cols];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (grid[r][c] == '1' && !visited[r][c]) {
DFS(r, c, grid, visited);
count++;
}
}
}
return count;
}Solution
Step 1: Identify missing visited check in DFS
The DFS function does not check if a cell is already visited before recursive calls, causing infinite recursion or revisiting.Step 2: Fix by adding visited check before recursion
Adding "if (visited[r][c]) return;" before marking visited prevents revisiting cells and infinite loops.Final Answer:
Add a check for visited[r][c] before recursive DFS calls -> Option BQuick Check:
Prevent revisiting by checking visited before DFS calls [OK]
- Not checking visited before recursion
- Confusing base case conditions
- Modifying grid instead of using visited array
Solution
Step 1: Understand connectivity rules
Original problem connects cells horizontally and vertically (4 directions). To include diagonals, add those directions.Step 2: Modify direction arrays for 8 directions
Add diagonal moves (-1,-1), (-1,1), (1,-1), (1,1) to dr and dc arrays to explore all neighbors.Final Answer:
Add diagonal directions (-1,-1), (-1,1), (1,-1), (1,1) to the direction arrays -> Option AQuick Check:
Include diagonals by adding their directions [OK]
- Ignoring diagonal neighbors
- Confusing BFS and DFS data structures
- Changing grid values instead of using visited array
Ready to prove it?
Pass the test and this pattern moves unknown
