Bird
Raised Fist0
Interview Prepgraphs-dfs-bfsmediumAmazonFacebookGoogleMicrosoftBloomberg

Number of Islands

Choose your preparation mode4 modes available
📋
Problem

Imagine you are analyzing satellite images of an archipelago to count how many separate islands exist in a vast ocean grid.

Given a 2D grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

m == grid.lengthn == grid[i].length1 ≤ m, n ≤ 300grid[i][j] is '0' or '1'
Edge cases: Grid with all water → 0 islandsGrid with all land → 1 islandGrid with single cell land → 1 island
</>
IDE
def numIslands(grid: List[List[str]]) -> int:public int numIslands(char[][] grid)int numIslands(vector<vector<char>>& grid)function numIslands(grid)
def numIslands(grid: List[List[str]]) -> int:
    # Write your solution here
    pass
class Solution {
    public int numIslands(char[][] grid) {
        // Write your solution here
        return 0;
    }
}
#include <vector>
using namespace std;

int numIslands(vector<vector<char>>& grid) {
    // Write your solution here
    return 0;
}
function numIslands(grid) {
    // Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: 0Not counting any islands due to missing DFS/BFS traversal or incorrect visited checks.✅ Add DFS/BFS traversal starting from each unvisited land cell and mark visited properly.
Wrong: Incorrect count merging diagonal neighborsCounting diagonally adjacent lands as connected islands.✅ Restrict DFS/BFS to only four directions: up, down, left, right.
Wrong: Multiple islands counted in all land gridNot marking visited cells properly, causing multiple counts of the same island.✅ Mark all connected lands visited during DFS/BFS to avoid recounting.
Wrong: Crash or error on empty gridNot handling empty grid or empty rows before traversal.✅ Add guard clause to return 0 if grid or grid[0] is empty.
Wrong: TLE on large inputUsing exponential or repeated traversal without visited marking.✅ Use O(m*n) DFS/BFS with visited set or in-place marking to avoid repeated work.
✓
Test Cases
t1_01basic
Input[[["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]]
Expected1

All connected '1's form one big island.

t1_02basic
Input[[["1","1","0","0","0"],["1","1","0","0","0"],["0","0","1","0","0"],["0","0","0","1","1"]]]
Expected3

Three separate islands: top-left 4 cells, middle single cell, bottom-right two cells.

t2_01edge
Input[[]]
Expected0

Empty grid has no islands.

t2_02edge
Input[[["0"]]]
Expected0

Single cell water grid has zero islands.

t2_03edge
Input[[["1"]]]
Expected1

Single cell land grid has one island.

t3_01corner
Input[[["1","0","1","0","1"],["0","1","0","1","0"],["1","0","1","0","1"],["0","1","0","1","0"]]]
Expected10

Checkerboard pattern: each '1' is isolated, so 10 islands total.

t3_02corner
Input[[["1","1","1","1","1"],["1","1","1","1","1"],["1","1","1","1","1"],["1","1","1","1","1"]]]
Expected1

All land grid forms one large island.

t3_03corner
Input[[["1","1","0","0","0"],["1","0","0","1","1"],["0","0","1","0","0"],["0","1","0","1","0"]]]
Expected5

Multiple islands with complex shapes and isolated cells.

t4_01performance
Input[[["1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0"],["0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1"],["1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0"],["0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1"],["1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0"],["0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1"],["1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0"],["0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1"],["1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0"],["0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1","0","1"]]]
⏱ Performance - must finish in 2000ms

Checkerboard pattern grid with 10 rows and 30 columns (300 cells). Must complete in O(m*n) time within 2 seconds.

Practice

(1/5)
1. Consider the following code snippet for the Keys and Rooms problem:
def canVisitAllRooms(rooms):
    n = len(rooms)
    visited = [false] * n
    count = 0
    def dfs(room):
        nonlocal count
        if visited[room]:
            return
        visited[room] = true
        count += 1
        if count == n:
            return
        for key in rooms[room]:
            dfs(key)
    dfs(0)
    return count == n

rooms = [[1], [2], [3], []]
print(canVisitAllRooms(rooms))
What is the value of count after the DFS call completes?
easy
A. 3
B. 0
C. 1
D. 4

Solution

  1. Step 1: Trace DFS calls starting from room 0

    Visit room 0 (count=1), then room 1 (count=2), then room 2 (count=3), then room 3 (count=4).
  2. Step 2: Confirm all rooms visited

    Since count equals total rooms (4), DFS stops early and returns true.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    All rooms reachable, count matches number of rooms [OK]
Hint: Count increments once per unique room visited [OK]
Common Mistakes:
  • Off-by-one error counting rooms
  • Assuming count stops at 3 instead of 4
  • Confusing count with length of visited list
2. What is the time complexity of the Union-Find based algorithm to check if a graph with V vertices and E edges is bipartite?
medium
A. O(V^2) because each union operation can take linear time
B. O(V + E log V) due to sorting edges before union
C. O((V + E) α(V)) where α is the inverse Ackermann function
D. O(V + E) because union-find operations are constant time

Solution

  1. Step 1: Identify number of union-find operations

    Each edge triggers at most one union operation, so total operations are O(E).
  2. Step 2: Analyze union-find operation complexity

    Union-Find with path compression and union by rank has amortized time O(α(V)) per operation, where α is inverse Ackermann function.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Union-Find complexity is near-linear, not quadratic or logarithmic [OK]
Hint: Union-Find operations are almost constant time amortized [OK]
Common Mistakes:
  • Assuming union is linear time
  • Confusing sorting necessity
  • Ignoring inverse Ackermann function
3. The following BFS code attempts to find the max area of an island in a grid. Identify the line that contains a subtle bug that can cause incorrect area calculation or runtime errors.
from collections import deque

def maxAreaOfIsland(grid):
    rows, cols = len(grid), len(grid[0])
    visited = set()
    max_area = 0

    for r in range(rows):
        for c in range(cols):
            if grid[r][c] == 1 and (r, c) not in visited:
                queue = deque([(r, c)])
                area = 0
                while queue:
                    row, col = queue.popleft()
                    # Bug: Missing visited check here
                    visited.add((row, col))
                    area += 1
                    for nr, nc in [(row+1,col),(row-1,col),(row,col+1),(row,col-1)]:
                        if grid[nr][nc] == 1 and (nr, nc) not in visited:
                            queue.append((nr, nc))
                max_area = max(max_area, area)
    return max_area
medium
A. Line that adds neighbors to the queue without boundary checks
B. Line that adds (row, col) to visited without checking if already visited
C. Line that initializes the queue with the starting cell
D. Line that updates max_area after BFS completes

Solution

  1. Step 1: Check neighbor addition line

    The code adds neighbors without verifying if nr, nc are within grid boundaries, risking index out of range errors.
  2. Step 2: Confirm other lines are correct

    Visited check before adding to queue is present, queue initialization and max_area update are correct.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Boundary checks missing cause runtime errors [OK]
Hint: Always check grid boundaries before accessing neighbors [OK]
Common Mistakes:
  • Forgetting boundary checks
  • Not checking visited before adding to queue
  • Adding visited check after popping queue
4. What is the time complexity of the optimal BFS approach for the Surrounded Regions problem on an m x n board?
medium
A. O(m * n) because each cell is visited at most once during BFS marking.
B. O(m * n * (m + n)) because each 'O' region is checked separately.
C. O(m * n * 4) due to checking four neighbors for each cell multiple times.
D. O(m + n) since only boundary cells are initially processed.

Solution

  1. Step 1: Analyze BFS traversal

    Each cell is enqueued and dequeued at most once during BFS marking, so total operations are proportional to the number of cells, m*n.
  2. Step 2: Consider neighbor checks

    Each cell checks up to 4 neighbors, but this is constant factor, so complexity remains O(m*n).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Linear scan plus BFS over all cells is O(m*n) [OK]
Hint: BFS visits each cell once, so O(m*n) time [OK]
Common Mistakes:
  • Confusing BFS with brute force approach leading to O(m*n*(m+n)).
  • Counting neighbor checks as multiplicative rather than constant factor.
  • Assuming only boundary cells matter for complexity.
5. Suppose the problem is modified so that water can flow uphill by at most 1 unit of height difference (i.e., from a cell to a neighbor if neighbor's height ≥ current height - 1). Which modification to the BFS approach correctly handles this variant?
hard
A. Change the BFS condition to allow neighbor heights >= current height - 1 and keep the rest unchanged.
B. No change needed; original BFS condition already covers uphill flow.
C. Run BFS from each cell individually to check uphill flow possibility.
D. Use a priority queue BFS (Dijkstra) to handle varying height constraints efficiently.

Solution

  1. Step 1: Understand uphill flow constraint

    Allowing uphill flow by 1 unit means edges have weights or costs, not uniform.
  2. Step 2: BFS is insufficient

    Standard BFS assumes uniform edge cost; to handle varying constraints, Dijkstra's algorithm with a priority queue is needed.
  3. Step 3: Modify algorithm

    Use priority queue BFS (Dijkstra) to explore cells with minimal cost respecting height difference constraints.
  4. Final Answer:

    Option D -> Option D
  5. Quick Check:

    Uphill flow requires weighted graph traversal -> Dijkstra [OK]
Hint: Uphill flow needs weighted BFS -> Dijkstra [OK]
Common Mistakes:
  • Trying to fix with simple BFS condition change
  • Running BFS from every cell causes TLE
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard