Hi👋SpeedAlgo • Deliberate Practice & Cognitive Ergonomics for Software Engineers

An interactive algorithm mastery and technical interview preparation platform published by Hi👋WebEnterprise. Built for senior and staff software engineers preparing for rigorous coding screens at top tech companies (FAANG/MAMAA).

13 Core Algorithmic Patterns & 225 Practice Problems

  • 1. Two Pointers (16 Paradigms, 43 Problems): Opposite ends, sorted pair sums, palindrome verification, trapping rain water, 3Sum, container with most water — includes the Sliding Window and Fast & Slow Pointers paradigms (contiguous subarray invariants, longest substrings, Floyd's cycle detection, linked list middle).
  • 2. Binary Search (9 Paradigms, 14 Problems): Monotonic predicate partitioning (feasible(x)), boundary search, rotated sorted arrays, square roots, minimum ship capacity, median of two sorted arrays, matrix median on value range.
  • 3. Bit Manipulation (5 Paradigms, 11 Problems): Counting set bits, XOR cancellation, bit reversal, bitmask pairing, maximum XOR with a bitwise trie.
  • 4. Math & Geometry (8 Paradigms, 14 Problems): Sieve of Eratosthenes, integer/roman conversions, modular arithmetic, geometric simulation.
  • 5. Tree/Graph Depth-First Search (15 Paradigms, 24 Problems): Path sums, lowest common ancestor, tree diameter, validating BSTs, tree DP (House Robber III, Binary Tree Cameras).
  • 6. Tree/Graph Breadth-First Search (5 Paradigms, 12 Problems): Level-order traversals, shortest path in unweighted graphs, zig-zag traversals, rotting oranges, word ladders.
  • 7. Graphs (12 Paradigms, 22 Problems): Topological sort, cycle detection, Dijkstra's algorithm, bipartite graph validation, network delay.
  • 8. Backtracking (6 Paradigms, 14 Problems): Subsets, permutations, combinations, constraint satisfaction, pruning, N-Queens, Sudoku solver.
  • 9. Dynamic Programming (13 Paradigms, 28 Problems): Memoization vs tabulation, 0/1 knapsack, unbounded knapsack, coin change, edit distance, longest common subsequence.
  • 10. Heap / Priority Queue (9 Paradigms, 11 Problems): Running medians, top-k elements, interval scheduling, IPO, k-way merges.
  • 11. Advanced Data Structures (7 Paradigms, 17 Problems): Trie (prefix tree), Union-Find (Disjoint Set Union), LRU Cache, LFU Cache, range-sum queries with updates.
  • 12. Stack (5 Paradigms, 9 Problems): Next greater element, largest rectangle in histogram, remove k digits, decode string, min stack.
  • 13. Intervals & Greedy (2 Paradigms, 6 Problems): Merge intervals, interval scheduling, meeting rooms by sweep line, jump game.

4-Stage Deliberate Practice Framework

  1. Stage 1 (Compare & Learn): Read the pattern's mental model, loop invariant and Big-O proof, compare the pattern's template with the problem's solution side by side, and use the step-by-step debugger. The solution can also be shown in C#, Java, TypeScript, C++, Go or Rust for almost every problem.
  2. Stage 2 (Active Recall): Rebuild the solution from memory in a code editor, with an invariant checklist and optional progressive hints, and check it against a judged test suite.
  3. Stage 3 (AI Interview Coach, coming soon): A mock-interview stage still in development; for now, students go straight from Stage 2 to Stage 4.
  4. Stage 4 (Solve on Your Own): Solve a new problem on your own against a 15-minute timer; your code is graded against a test suite. Python and TypeScript run in your browser and C# runs on our server (design problems grade in Python and TypeScript).

Equipped with a spaced-repetition review hub on a fixed 7-step schedule (1 day up to 90 days), a two-pane Studio workspace, and study notes.

Pricing, Access & Commercial Terms

  • Core Curriculum: 100% Free. No credit card required.
  • Coins: New accounts get 40 free coins once, the daily claim adds +20 coins once a day, and inviting a friend earns you +25 coins when they complete their first practice step. These are the only ways to earn coins.
  • AI Coach: Each AI coach question costs 1-5 coins, priced by the server according to its size.
  • BYOK (Bring Your Own Key): AI coaching is free with your own Google Gemini, OpenAI or OpenRouter API key (BYOK).
  • Extras: Coins also unlock extras for 24 hours: a Recall hint level (1 coin), a Solve solution reveal (2), a LeetCode problem card's solutions (1) and a pattern's extra canonical problems (1).
  • Payments & Refunds: Nothing on the site is sold for money: coins can only be earned, never bought. There are no subscriptions or charges, so there is nothing to refund.
  • Platform Operator: Hi👋WebEnterprise. Support & policies at hispeedalgo.com.
Skip to main content
Hi👋SpeedAlgo

Invariant-First Algorithmic Mastery

Arena
238Items
Theory Context•Graph Algorithms
MediumLC 200

Number of Islands (LeetCode 200)

Target Frequency:AmazonMicrosoftGoogle

You get an m x n grid grid of '1' (land) and '0' (water) cells, forming a map surrounded on all four sides by water. Count how many islands it contains, where an island is a group of land cells chained together through up/down/left/right neighbors.

Return that count.

Worked Examples

Example 1
Input:grid = [["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]
Output:1
Explanation: All the land cells are 4-directionally connected into a single island.
Example 2
Input:grid = [["1","1","0","0","0"],["1","1","0","0","0"],["0","0","1","0","0"],["0","0","0","1","1"]]
Output:3
Explanation: Three separate groups of connected land cells, each surrounded by water.

⚖️Formal Constraints & Bounds

  • m == grid.length

  • n == grid[i].length

  • 1 <= m, n <= 300

  • grid[i][j] is '0' or '1'.

Deep-Dive & Conceptual Insights

Core Insight

Each connected component of '1's forms one island. Sinking visited land cells (e.g. setting them to '0') avoids separate visited set overhead.

Real-World Scenario & Production Applications

Image segmentation in computer vision and counting connected user communities in social networks both rely on connected-component grid flood-fills.

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Grid Component Scanning

Iterate over every cell (r, c). Upon discovering an unvisited land cell (grid[r][c] == '1'), increment island count and initiate traversal.

Mathematical Recurrence / Code Invariant
island_count = 0
for r in range(R):
    for c in range(C):
        if grid[r][c] == "1":
            island_count += 1
            dfs(r, c)

Step-by-Step Execution Trace Table

StepOuter Scan CoordinateCell StateFlood Fill ActionCells Sunk to '0'Island Count
1(0,0)Land ('1'), unvisitedDiscover Island #1 →\to→ DFS drain(0,0), (1,0), (0,1)1
2(0,1)Already sunk ('0')Skip in O(1)O(1)O(1)—1
3(0,2), (0,3)Water ('0')Skip—1
4(0,4)Land ('1'), unvisitedDiscover Island #2 →\to→ DFS drain(0,4), (1,4)2
5(1,0)Already sunk ('0')Skip in O(1)O(1)O(1)—2
6(1,1)–(1,3)Water ('0')Skip—2
7(1,4)Already sunk ('0')Skip in O(1)O(1)O(1)—2
8(2,0), (2,1)Water ('0')Skip—2
9(2,2)Land ('1'), unvisitedDiscover Island #3 →\to→ DFS drain(2,2) alone3
10(2,3), (2,4)Water ('0')Skip—3 (Done)
Trace Inputgrid = [["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]
Expected1
StepOuter Scan CoordinateCell StateFlood Fill ActionCells Sunk to '0'Island Count
1(0,0)Land ('1'), unvisitedDiscover Island #1 →\to→ DFS drain(0,0), (1,0), (0,1)1
2(0,1)Already sunk ('0')Skip in O(1)O(1)O(1)—1
3(0,2), (0,3)Water ('0')Skip—1
4(0,4)Land ('1'), unvisitedDiscover Island #2 →\to→ DFS drain(0,4), (1,4)2
5(1,0)Already sunk ('0')Skip in O(1)O(1)O(1)—2
6(1,1)–(1,3)Water ('0')Skip—2
7(1,4)Already sunk ('0')Skip in O(1)O(1)O(1)—2
8(2,0), (2,1)Water ('0')Skip—2
9(2,2)Land ('1'), unvisitedDiscover Island #3 →\to→ DFS drain(2,2) alone3
10(2,3), (2,4)Water ('0')Skip—3 (Done)
Code Shape
Archetype Code Shape
Python
1R, C = len(grid), len(grid[0])
2islands = 0
3for r in range(R):
4 for c in range(C):
5 if grid[r][c] == "1":
6 islands += 1
7 stack = [(r, c)]
8 grid[r][c] = "0"
9 while stack:
10 curr_r, curr_c = stack.pop()
11 for each in-bounds neighbour (nr, nc) with grid[nr][nc] == "1":
12 grid[nr][nc] = "0"
13 stack.append((nr, nc))
14return islands

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

Counting islands sounds like a geometry problem, but it's really a foundational graph question wearing a grid costume: every land cell is a node, and two adjacent land cells share an edge.

🏝️ The Analogy: Sinking Each Island as You Count It

Imagine scanning a map left-to-right, top-to-bottom, looking for unclaimed land. The moment you spot one, you know you've found a new island, so you count it — then you immediately "sink" that entire island (and every cell connected to it) so your scan never mistakes it for a second island later. Sinking an entire connected blob is exactly what a flood-fill traversal (BFS or DFS) does: start at one land cell, spread to every reachable neighboring land cell, marking each one visited so it's permanently excluded from future counting.

🔑 The Key Idea in the Code

The outer double-loop only ever increments islands when it lands on land that hasn't already been claimed by an earlier flood-fill — everything the inner while loop touches is turned to "0" so the outer scan glides right over it.

  • Marking visited on pop instead of push in BFS: Waiting until a cell is popped from the queue to mark it '0' (or visited). Multiple neighboring cells will discover and enqueue the same cell, causing queue memory to grow exponentially to O(4MN)O(4^{MN})O(4MN).

  • Destructive mutation side-effects: Mutating grid[r][c] = '0' in place when the interviewer specifies that the input grid is immutable or read-only. Clarify whether grid mutation is allowed; if not, maintain an explicit visited set.

  • String '1' vs integer 1 type mismatch: Checking if grid[r][c] == 1 instead of == '1'. LeetCode provides grid as a list of strings, so integer comparison silently evaluates to False on all cells.

  • Python Recursion Limit Crash: for large snake-like islands (N = 300), DFS depth can exceed Python's default recursion limit (1000). A Senior SWE uses an iterative queue (BFS) or sys.setrecursionlimit(200000) in production systems.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

The grid holds "1" (land) and "0" (water), and an island is land "connected horizontally or vertically": the task is to count separate groups of joined cells, which is Flood Fill: one scan for new groups, one search per group.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Between searches, every land cell turned to "0" belongs to an island already counted in islands, and every "1" left belongs to one not counted yet. So the outer scan meeting a "1" means a new island: count it once, then flood it.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • islands += 1 belongs in the outer scan, once per search: inside the while stack loop it counts cells, not islands.

  • grid[nr][nc] = "0" goes with stack.append((nr, nc)): marking on pop instead lets a cell be pushed by several neighbours before it is ever popped.

  • 0 <= nr < R and 0 <= nc < C comes before grid[nr][nc]: a cell on the edge has neighbours outside the grid: nr = -1 silently reads the last row through Python's negative index, and nr = R raises IndexError.

The 60-Second Interview Pitch

Say this out loud before you type a single line

"Counting islands is counting groups of joined land cells, so I'd use Flood Fill. I scan every cell. When I meet a one, that's land no search has reached, so it starts a new island: I add one to the count and flood that island with a stack search. Every land cell the search reaches is turned to zero as I push it, so the scan never meets that island again, and each island is counted exactly once. The trap is where the counter lives: it goes in the outer scan, once per search, never inside the flood, where it would count cells instead of islands. I use an explicit stack, not recursion, so a big snake-shaped island can't pass the recursion limit. Every cell is read by the scan and pushed at most once, so it's O(R times C) time, and O(R times C) space for the stack in the worst case."

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(R * C)

Look at the code: the two for loops read each of the R * C cells once. A land cell enters stack only while it is still "1", and it is turned to "0" at that moment (the first cell right after the scan finds it, every other cell together with stack.append), so each cell is pushed and popped at most once. Each pop checks 4 neighbours with O(1) work. Total: R * C scan steps plus at most 4 * R * C neighbour checks, O(R * C).

SPACE COMPLEXITY

O(R * C)

There is no recursion: the search keeps its cells in the explicit stack on the heap. A cell is marked as it is pushed, so it is never in stack twice, and stack holds at most R * C cells; on an all-land grid it grows to about half the cells. The grid is changed in place, so there is no visited set.

Formal Recurrence Relation

T(R, C) = R * C (scan) + R * C (pushes and pops) + 4 * R * C (neighbour checks) = O(R * C)

Derivation Progression

Outer scan

for r in range(R): for c in range(C): R * C cell checks

Each cell is read once; a "1" starts a new island and a search.

Each land cell is pushed once

grid[nr][nc] = "0" right before stack.append((nr, nc)): at most R * C pushes and pops

A cell turns to "0" as it is pushed, so no later neighbour can push it again.

Four neighbour checks per pop

for dr, dc in 4 directions: at most 4 * R * C checks, O(1) each

The bounds test and the "1" test cost O(1) per neighbour.

Variable Definitions

RRR

Number of rows, len(grid)

CCC

Number of columns, len(grid[0])

Memory Architecture & Bounds

🟣 Call Stack

O(1): no recursion

🔵 Auxiliary Heap

O(R * C): the explicit stack; cells are marked on push, so each cell enters it at most once

🟢 Output Space

O(1): one integer, islands

Boundary Best / Worst Cases

Best Case

O(R∗C)O(R * C)O(R∗C) all water: the scan still reads every cell, and stack stays empty.

Average Case

O(R∗C)O(R * C)O(R∗C).

Worst Case

O(R∗C)O(R * C)O(R∗C) all land: one search pushes every cell, and stack holds about half of them at its peak.

Graph & Tree Traversal Frontier

Graph & Tree Traversal Frontier
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Scale signal: images and maps with millions of cells. One scan plus one search per island stays O(R⋅C)O(R \cdot C)O(R⋅C), while searching again from every land cell would be quadratic.

CONSTRAINTS & BOUNDS

R,C≤300R, C \le 300R,C≤300, so at most 9×1049 \times 10^49×104 cells. The grid is changed in place, so the only extra memory is the stack, which on an all-land grid grows to about half the cells.

FAANG PRODUCTION TRAPS & EDGE CASES

For a very large image, even the explicit stack can hold a large fraction of all cells. Image libraries label components row by row instead, joining labels from the row above with union-find, so memory stays close to one row of labels plus the label table.

Core Algorithmic State Invariants

  1. Example 2, Island by Island

The scan meets (0, 0) first: islands = 1, and the search turns the 2 x 2 block of land to "0". It then meets (2, 2): islands = 2, a single cell. Last is (3, 3): islands = 3, the pair (3, 3) and (3, 4).

  1. Diagonal Cells Are Separate

Only up, down, left and right join cells. In [["1", "0"], ["0", "1"]] the two land cells touch only at a corner, so the scan starts two searches and the answer is 2.

Theory Context•Graph Algorithms
MediumLC 200

Number of Islands (LeetCode 200)

Target Frequency:AmazonMicrosoftGoogle

You get an m x n grid grid of '1' (land) and '0' (water) cells, forming a map surrounded on all four sides by water. Count how many islands it contains, where an island is a group of land cells chained together through up/down/left/right neighbors.

Return that count.

Worked Examples

Example 1
Input:grid = [["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]
Output:1
Explanation: All the land cells are 4-directionally connected into a single island.
Example 2
Input:grid = [["1","1","0","0","0"],["1","1","0","0","0"],["0","0","1","0","0"],["0","0","0","1","1"]]
Output:3
Explanation: Three separate groups of connected land cells, each surrounded by water.

⚖️Formal Constraints & Bounds

  • m == grid.length

  • n == grid[i].length

  • 1 <= m, n <= 300

  • grid[i][j] is '0' or '1'.

Deep-Dive & Conceptual Insights

Core Insight

Each connected component of '1's forms one island. Sinking visited land cells (e.g. setting them to '0') avoids separate visited set overhead.

Real-World Scenario & Production Applications

Image segmentation in computer vision and counting connected user communities in social networks both rely on connected-component grid flood-fills.

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Grid Component Scanning

Iterate over every cell (r, c). Upon discovering an unvisited land cell (grid[r][c] == '1'), increment island count and initiate traversal.

Mathematical Recurrence / Code Invariant
island_count = 0
for r in range(R):
    for c in range(C):
        if grid[r][c] == "1":
            island_count += 1
            dfs(r, c)

Step-by-Step Execution Trace Table

StepOuter Scan CoordinateCell StateFlood Fill ActionCells Sunk to '0'Island Count
1(0,0)Land ('1'), unvisitedDiscover Island #1 →\to→ DFS drain(0,0), (1,0), (0,1)1
2(0,1)Already sunk ('0')Skip in O(1)O(1)O(1)—1
3(0,2), (0,3)Water ('0')Skip—1
4(0,4)Land ('1'), unvisitedDiscover Island #2 →\to→ DFS drain(0,4), (1,4)2
5(1,0)Already sunk ('0')Skip in O(1)O(1)O(1)—2
6(1,1)–(1,3)Water ('0')Skip—2
7(1,4)Already sunk ('0')Skip in O(1)O(1)O(1)—2
8(2,0), (2,1)Water ('0')Skip—2
9(2,2)Land ('1'), unvisitedDiscover Island #3 →\to→ DFS drain(2,2) alone3
10(2,3), (2,4)Water ('0')Skip—3 (Done)
Trace Inputgrid = [["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]
Expected1
StepOuter Scan CoordinateCell StateFlood Fill ActionCells Sunk to '0'Island Count
1(0,0)Land ('1'), unvisitedDiscover Island #1 →\to→ DFS drain(0,0), (1,0), (0,1)1
2(0,1)Already sunk ('0')Skip in O(1)O(1)O(1)—1
3(0,2), (0,3)Water ('0')Skip—1
4(0,4)Land ('1'), unvisitedDiscover Island #2 →\to→ DFS drain(0,4), (1,4)2
5(1,0)Already sunk ('0')Skip in O(1)O(1)O(1)—2
6(1,1)–(1,3)Water ('0')Skip—2
7(1,4)Already sunk ('0')Skip in O(1)O(1)O(1)—2
8(2,0), (2,1)Water ('0')Skip—2
9(2,2)Land ('1'), unvisitedDiscover Island #3 →\to→ DFS drain(2,2) alone3
10(2,3), (2,4)Water ('0')Skip—3 (Done)
Code Shape
Archetype Code Shape
Python
1R, C = len(grid), len(grid[0])
2islands = 0
3for r in range(R):
4 for c in range(C):
5 if grid[r][c] == "1":
6 islands += 1
7 stack = [(r, c)]
8 grid[r][c] = "0"
9 while stack:
10 curr_r, curr_c = stack.pop()
11 for each in-bounds neighbour (nr, nc) with grid[nr][nc] == "1":
12 grid[nr][nc] = "0"
13 stack.append((nr, nc))
14return islands

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

Counting islands sounds like a geometry problem, but it's really a foundational graph question wearing a grid costume: every land cell is a node, and two adjacent land cells share an edge.

🏝️ The Analogy: Sinking Each Island as You Count It

Imagine scanning a map left-to-right, top-to-bottom, looking for unclaimed land. The moment you spot one, you know you've found a new island, so you count it — then you immediately "sink" that entire island (and every cell connected to it) so your scan never mistakes it for a second island later. Sinking an entire connected blob is exactly what a flood-fill traversal (BFS or DFS) does: start at one land cell, spread to every reachable neighboring land cell, marking each one visited so it's permanently excluded from future counting.

🔑 The Key Idea in the Code

The outer double-loop only ever increments islands when it lands on land that hasn't already been claimed by an earlier flood-fill — everything the inner while loop touches is turned to "0" so the outer scan glides right over it.

  • Marking visited on pop instead of push in BFS: Waiting until a cell is popped from the queue to mark it '0' (or visited). Multiple neighboring cells will discover and enqueue the same cell, causing queue memory to grow exponentially to O(4MN)O(4^{MN})O(4MN).

  • Destructive mutation side-effects: Mutating grid[r][c] = '0' in place when the interviewer specifies that the input grid is immutable or read-only. Clarify whether grid mutation is allowed; if not, maintain an explicit visited set.

  • String '1' vs integer 1 type mismatch: Checking if grid[r][c] == 1 instead of == '1'. LeetCode provides grid as a list of strings, so integer comparison silently evaluates to False on all cells.

  • Python Recursion Limit Crash: for large snake-like islands (N = 300), DFS depth can exceed Python's default recursion limit (1000). A Senior SWE uses an iterative queue (BFS) or sys.setrecursionlimit(200000) in production systems.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

The grid holds "1" (land) and "0" (water), and an island is land "connected horizontally or vertically": the task is to count separate groups of joined cells, which is Flood Fill: one scan for new groups, one search per group.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Between searches, every land cell turned to "0" belongs to an island already counted in islands, and every "1" left belongs to one not counted yet. So the outer scan meeting a "1" means a new island: count it once, then flood it.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • islands += 1 belongs in the outer scan, once per search: inside the while stack loop it counts cells, not islands.

  • grid[nr][nc] = "0" goes with stack.append((nr, nc)): marking on pop instead lets a cell be pushed by several neighbours before it is ever popped.

  • 0 <= nr < R and 0 <= nc < C comes before grid[nr][nc]: a cell on the edge has neighbours outside the grid: nr = -1 silently reads the last row through Python's negative index, and nr = R raises IndexError.

The 60-Second Interview Pitch

Say this out loud before you type a single line

"Counting islands is counting groups of joined land cells, so I'd use Flood Fill. I scan every cell. When I meet a one, that's land no search has reached, so it starts a new island: I add one to the count and flood that island with a stack search. Every land cell the search reaches is turned to zero as I push it, so the scan never meets that island again, and each island is counted exactly once. The trap is where the counter lives: it goes in the outer scan, once per search, never inside the flood, where it would count cells instead of islands. I use an explicit stack, not recursion, so a big snake-shaped island can't pass the recursion limit. Every cell is read by the scan and pushed at most once, so it's O(R times C) time, and O(R times C) space for the stack in the worst case."

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(R * C)

Look at the code: the two for loops read each of the R * C cells once. A land cell enters stack only while it is still "1", and it is turned to "0" at that moment (the first cell right after the scan finds it, every other cell together with stack.append), so each cell is pushed and popped at most once. Each pop checks 4 neighbours with O(1) work. Total: R * C scan steps plus at most 4 * R * C neighbour checks, O(R * C).

SPACE COMPLEXITY

O(R * C)

There is no recursion: the search keeps its cells in the explicit stack on the heap. A cell is marked as it is pushed, so it is never in stack twice, and stack holds at most R * C cells; on an all-land grid it grows to about half the cells. The grid is changed in place, so there is no visited set.

Formal Recurrence Relation

T(R, C) = R * C (scan) + R * C (pushes and pops) + 4 * R * C (neighbour checks) = O(R * C)

Derivation Progression

Outer scan

for r in range(R): for c in range(C): R * C cell checks

Each cell is read once; a "1" starts a new island and a search.

Each land cell is pushed once

grid[nr][nc] = "0" right before stack.append((nr, nc)): at most R * C pushes and pops

A cell turns to "0" as it is pushed, so no later neighbour can push it again.

Four neighbour checks per pop

for dr, dc in 4 directions: at most 4 * R * C checks, O(1) each

The bounds test and the "1" test cost O(1) per neighbour.

Variable Definitions

RRR

Number of rows, len(grid)

CCC

Number of columns, len(grid[0])

Memory Architecture & Bounds

🟣 Call Stack

O(1): no recursion

🔵 Auxiliary Heap

O(R * C): the explicit stack; cells are marked on push, so each cell enters it at most once

🟢 Output Space

O(1): one integer, islands

Boundary Best / Worst Cases

Best Case

O(R∗C)O(R * C)O(R∗C) all water: the scan still reads every cell, and stack stays empty.

Average Case

O(R∗C)O(R * C)O(R∗C).

Worst Case

O(R∗C)O(R * C)O(R∗C) all land: one search pushes every cell, and stack holds about half of them at its peak.

Graph & Tree Traversal Frontier

Graph & Tree Traversal Frontier
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Scale signal: images and maps with millions of cells. One scan plus one search per island stays O(R⋅C)O(R \cdot C)O(R⋅C), while searching again from every land cell would be quadratic.

CONSTRAINTS & BOUNDS

R,C≤300R, C \le 300R,C≤300, so at most 9×1049 \times 10^49×104 cells. The grid is changed in place, so the only extra memory is the stack, which on an all-land grid grows to about half the cells.

FAANG PRODUCTION TRAPS & EDGE CASES

For a very large image, even the explicit stack can hold a large fraction of all cells. Image libraries label components row by row instead, joining labels from the row above with union-find, so memory stays close to one row of labels plus the label table.

Core Algorithmic State Invariants

  1. Example 2, Island by Island

The scan meets (0, 0) first: islands = 1, and the search turns the 2 x 2 block of land to "0". It then meets (2, 2): islands = 2, a single cell. Last is (3, 3): islands = 3, the pair (3, 3) and (3, 4).

  1. Diagonal Cells Are Separate

Only up, down, left and right join cells. In [["1", "0"], ["0", "1"]] the two land cells touch only at a corner, so the scan starts two searches and the answer is 2.

© 2026 Hi👋WebEnterprise. All rights reserved.
Sitemap•llms.txt•