Make A Large Island

Leetcode Daily Challenge

Posted by Haoran on August 1, 2021

Problem

You are given an n x n binary matrix grid. You are allowed to change at most one 0 to be 1.

Return the size of the largest island in grid after applying this operation.

An island is a 4-directionally connected group of 1s.

Constraints

n == grid.length
n == grid[i].length
1 <= n <= 500
grid[i][j] is either 0 or 1.\

Thinking

  • Matrix problem

  • No idea at first, search for article online

  • Union - Find, we could form a union of one’s, and store the area of islands in the parent element.
    • In this way, we can get the area of each island easily in O(1)
  • Next we traverse each element and try to turn 0 to 1. Sum up the area of its four neighbors, and compare the result to current max

  • Time Complexity: O(N^2)
    • Use find to re-organize union each time
  • Implemention:
    • Give each island a unique number, keep island and corresponding area in a dictionary. Use a dfs to sum up the area.
  • Reflect:
    • This is a tricky one, even though figured out how to do it. Thera are still quite a lot of implementaion details.
    • Next time, remember to use dfs to traverse and get the islands. Use an additional dictionary to keep track of each island’s area.
from typing import List


def largestIsland(grid: List[List[int]]) -> int:
    n = len(grid)
    island_index = [[-1 for y in range(n)] for x in range(n)]

    index = 0
    area = {}

    def generate_neighbors(i, j):
        moves = [[-1, 0], [0, -1], [1, 0], [0, 1]]
        for move in moves:
            dx = move[0]
            dy = move[1]
            if i + dx >= 0 and i + dx < n and j + dy >= 0 and j + dy < n:
                yield(i+dx, j+dy)

    def dfs(i, j, index):
        area_sum = 1
        island_index[i][j] = index
        for neighbor in generate_neighbors(i, j):
            x = neighbor[0]
            y = neighbor[1]
            if grid[x][y] == 1 and island_index[x][y] == -1:
                area_sum += dfs(x, y, index)

        return area_sum

    for i in range(n):
        for j in range(n):
            # Not yet assigned to an island
            if grid[i][j] == 1 and island_index[i][j] == -1:

                area[index] = dfs(i, j, index)
                index += 1
    if area:
        max_area = max(area.values())
    else:
        max_area = 0
    for i in range(n):
        for j in range(n):
            if grid[i][j] == 0:
                # Try to change current 0 to 1
                cur_area = 1
                index_set = set()
                for x, y in generate_neighbors(i, j):
                    if grid[x][y] == 1:
                        index_set.add(island_index[x][y])
                for index in index_set:
                    cur_area += area[index]
                max_area = max(max_area, cur_area)
    return max_area


if __name__ == "__main__":
    print(largestIsland([[1, 0], [0, 1]]))