本文已参与「新人创作礼」活动,一起开启掘金创作之路。
827. 最大人工岛
示例 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] 为 0 或 1
思路
首先,先不要管 讲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;
}
};