[每日一题] leetcode 827. 最大人工岛

119 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

827. 最大人工岛

给你一个大小为nxn二进制矩阵grid。最多只能将一格 0变成 1给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。

返回执行此操作后,grid中最大的岛屿面积是多少?返回执行此操作后,grid 中最大的岛屿面积是多少?

岛屿由一组上、下、左、右四个方向相连的 1形成。岛屿 由一组上、下、左、右四个方向相连的 1 形成。

  示例 1:

输入: grid = [[1, 0], [0, 1]]
输出: 3
解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。

示例 2:

输入: grid = [[1, 1], [1, 0]]
输出: 4
解释: 将一格0变成1,岛屿的面积扩大为 4

示例 3:

输入: grid = [[1, 1], [1, 1]]
输出: 4
解释: 没有0可以让我们变成1,面积依然为 4

提示:

n == grid.length
n == grid[i].length
1 <= n <= 500
grid[i][j]01

思路

首先,先不要管 讲0变为1,我们可以得到最大的面积,应该怎么计算?
显然,我们需要使用dfs来计算
其次,我们再来考虑加一个格子之后,可以联通哪些区域,加一个格子之后,可以联通上下左右几块区域
那么对于这些区域来说,我们可以用O(n^2)的时间先预处理出来,然后我们就可以每次O(1)求出增加1个单元格可以联通的最大区域的面积
类似于并查集一样

代码

class Solution {
public:
    int largestIsland(vector<vector<int>>& grid) {
        int xx[] = {0, 0, 1, -1};
        int yy[] = {1, -1, 0, 0};
        int n = grid.size(), m = grid.back().size();
        vector<vector<int>> un(n, vector<int>(m));
        function<void(int, int, int, int&)> dfs = 
            [&](int x, int y, int tag, int& res) -> void {
            res ++; un[x-1][y-1] = tag;
            for (int i = 0; i < 4; i ++) {
                int dx = x + xx[i];
                int dy = y + yy[i];
                if (dx < 1 || dy < 1 || dx > n || dy > m) continue;
                if (!grid[dx-1][dy-1] || un[dx-1][dy-1]) continue;
                un[dx-1][dy-1] = tag;
                dfs(dx, dy, tag, res);
            }
        };
        vector<int> res;
        int ans = 0;
        for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            if (grid[i-1][j-1] && un[i-1][j-1] == 0) {
                int tmp = 0;
                dfs(i, j, res.size() + 1, tmp);
                res.push_back(tmp);
                ans = max(ans, tmp);
            }
        for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++) {
            if (grid[i-1][j-1]) continue;
            set<int> st;
            for (int k = 0; k < 4; k ++) {
                int dx = i + xx[k];
                int dy = j + yy[k];
                if (dx < 1 || dy < 1 || dx > n || dy > m) continue;
                if (!grid[dx-1][dy-1]) continue;
                st.insert(un[dx-1][dy-1]);
            }
            int tmp = 0;
            for (auto v : st) tmp += res[v-1];
            ans = max(ans, tmp + 1);
        }
        return ans;
    }
};