Making A Large Island

HardGraph DFS · Component Labeling🧩 Graph DFSLeetCode #827 ↗Updated

Problem

You are given an n x n binary grid where 1 is land and 0 is water. You may turn at most one water cell into land. Return the size of the largest island you can end up with, where an island is a group of land cells connected up, down, left or right.
Inputgrid = [[1,0],[0,1]]Output3
Inputgrid = [[1,1],[1,0]]Output4
Inputgrid = [[1,1],[1,1]]Output4

1 ≤ n ≤ 500  ·  grid[i][j] is 0 or 1

Try it yourself

Java
class Solution {
    public int largestIsland(int[][] grid) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Flipping a water cell merges the islands touching it. So measure every island once, tag each land cell with its island id, and the score of a water cell is 1 + the sizes of its distinct neighbouring ids — no re-flooding per flip.
PatternGraph DFS

Instinct Connected regions, all paths, reachability, cloning or 2-colouring a graph or grid: dive from a node, mark it, recurse into unvisited neighbours.

Memory hack Mark before you march: go deep, paint as you go, and back up only when every door is already painted.

Open the Graph DFS guide →

Approaches

Brute ForceFlip Each Zero, Flood-Fill from It

Time O(n4)Space O(n²)

Try every water cell: set it to 1, flood-fill from it to measure the island it now belongs to, then set it back. If the grid has no water at all, the whole grid is one island of size n². (If any water exists, the best island always contains a flipped cell, because any island smaller than the grid borders water.)

Java
private static final int[][] DIRS = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

public int largestIsland(int[][] grid) {
    int n = grid.length, best = 0;
    boolean hasWater = false;
    for (int r = 0; r < n; r++) {
        for (int c = 0; c < n; c++) {
            if (grid[r][c] != 0) continue;
            hasWater = true;
            grid[r][c] = 1; // try this flip
            best = Math.max(best, islandSize(grid, r, c));
            grid[r][c] = 0; // undo
        }
    }
    return hasWater ? best : n * n;
}
private int islandSize(int[][] grid, int sr, int sc) {
    int n = grid.length, size = 0;
    boolean[][] seen = new boolean[n][n];
    Deque<int[]> stack = new ArrayDeque<>();
    stack.push(new int[]{sr, sc});
    seen[sr][sc] = true;
    while (!stack.isEmpty()) {
        int[] cell = stack.pop();
        size++;
        for (int[] d : DIRS) {
            int r = cell[0] + d[0], c = cell[1] + d[1];
            if (r >= 0 && r < n && c >= 0 && c < n && !seen[r][c] && grid[r][c] == 1) {
                seen[r][c] = true;
                stack.push(new int[]{r, c});
            }
        }
    }
    return size;
}

Direct simulation, but up to n² flips × n² per flood is ~6·1010 at n = 500.

At a glance

LevelApproachTimeSpace
Brute ForceFlip Each Zero, Flood-Fill from ItO(n4)O(n²)
BetterUnion-Find with Component SizesO(n² · α(n²))O(n²)
OptimalLabel Islands In-Place, Then Score Each ZeroO(n²)O(n²)
Common pitfalls
  • Adding the same island twice when it touches the flipped cell on two sides — dedupe ids.
  • Returning 0 (or forgetting) the all-land grid where no flip is possible — answer is n².
  • Recursive DFS on a 500×500 island can overflow the stack — prefer an explicit stack.
Interview tips
  • Start from “try every flip”, then ask what work is repeated (re-flooding islands).
  • Explain why a flipped cell contributes 1 + sum of distinct neighbour islands.
  • Mention that labelling mutates the grid; copy it if the caller needs it intact.
Pattern
Connected-component labelling + per-cell merge scoring → “change one cell, maximise a component” grid questions.
My notes saved in this browser