Skip to content

Making A Large Island⚓︎

Link

Description⚓︎

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.

Example 1:

  • Input: grid = [[1,0],[0,1]]
  • Output: 3
  • Explanation: Change one 0 to 1 and connect two 1s, then we get an island with area = 3.

Example 2:

  • Input: grid = [[1,1],[1,0]]
  • Output: 4
  • Explanation: Change the 0 to 1 and make the island bigger, only one island with area = 4.

Example 3:

  • Input: grid = [[1,1],[1,1]]
  • Output: 4
  • Explanation: Can't change any 0 to 1, only one island with area = 4.

Constraints:

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

Solution⚓︎

class Solution {
private:
    int m, n;
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
    void dfs(vector<vector<int>>& grid, int i, int j, int id) {
        if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] != 1) return;
        grid[i][j] = id;  // if grid[i][j] == 1
        for (int k = 0; k < 4; k++) {
            dfs(grid, i + dx[k], j + dy[k], id);
        }
    }

public:
    int largestIsland(vector<vector<int>>& grid) {
        m = grid.size(); n = grid[0].size();
        int id = 2;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                dfs(grid, i, j, id++);
            }
        }
        unordered_map<int, int> sizeMap;
        int maxSize = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] > 1) {
                    maxSize = max(maxSize, ++sizeMap[grid[i][j]]);
                }
            }
        }

        vector<bool> visited(id, false);
        int up, down, left, right, merge;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 0) {
                    up = (i > 0) ? grid[i - 1][j] : 0;
                    down = (i + 1 < m) ? grid[i + 1][j] : 0;
                    left = (j > 0) ? grid[i][j - 1] : 0;
                    right = (j + 1 < n) ? grid[i][j + 1] : 0;

                    visited[up] = true;
                    merge = 1 + sizeMap[up];
                    if (!visited[down]) {
                        merge += sizeMap[down]; visited[down] = true;
                    }
                    if (!visited[left]) {
                        merge += sizeMap[left]; visited[left] = true;
                    }
                    if (!visited[right]) {
                        merge += sizeMap[right]; visited[right] = true;
                    }
                    maxSize = max(maxSize, merge);

                    visited[up] = false;
                    visited[down] = false;
                    visited[left] = false;
                    visited[right] = false;
                }
            }
        }
        return maxSize;
    }
};
  • Time complexity: \(O(nm)\).

Answer 2⚓︎

class Solution {
private:
    int m, n;
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

    int dfs(const vector<vector<int>>& grid, int x, int y, vector<vector<int>>& tag, int id) {
        int res = 1;
        tag[x][y] = id;
        for (int i = 0; i < 4; i++) {
            int newX = x + dx[i], newY = y + dy[i];
            if (newX < 0 || newX >= m || newY < 0 || newY >= n) continue;
            if (grid[newX][newY] == 1 && tag[newX][newY] == 0) {
                res += dfs(grid, newX, newY, tag, id);
            }
        }
        return res;
    }

public:
    int largestIsland(vector<vector<int>>& grid) {
        m = grid.size(); n = grid[0].size();
        int res = 0;
        vector<vector<int>> tag(m, vector<int>(n, 0));
        unordered_map<int, int> area;

        int id = 1;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1 && tag[i][j] == 0) {
                    area[id] = dfs(grid, i, j, tag, id);
                    res = max(res, area[id]);
                    id++;
                }
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 0) {
                    int merge = 1;
                    unordered_set<int> connected;

                    for (int k = 0; k < 4; k++) {
                        int x = i + dx[k], y = j + dy[k];
                        if (x < 0 || x >= m || y < 0 || y >= n || tag[x][y] == 0 || connected.count(tag[x][y]) > 0)
                            continue;
                        merge += area[tag[x][y]];
                        connected.insert(tag[x][y]);
                    }
                    res = max(res, merge);
                }
            }
        }

        return res;
    }
};