hard题目,十分困难哈,不是简单的岛屿套路,而是要经历过两次遍历,先一次遍历岛屿再一次遍历海洋
题目
给你一个大小为 n x n
二进制矩阵 grid
。最多 只能将一格 0
变成 1
。
返回执行此操作后,grid
中最大的岛屿面积是多少?
岛屿 由一组上、下、左、右四个方向相连的 1
形成。
示例 1:
输入: grid = [[1, 0], [0, 1]]
输出: 3
解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。
代码与解析
class Solution {
int n;
Map<Integer, Integer> map = new HashMap<>();
public int largestIsland(int[][] grid) {
n = grid.length;
int ans = 0;
int index = 2;
// 遍历整个 grid,标记陆地并计算各个岛屿的面积
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
int t = land(grid, i, j, index); // 标记岛屿并计算面积
map.put(index, t); // 将岛屿编号和面积存入 map
index++;
ans = Math.max(ans, t); // 更新最大岛屿面积
}
}
}
// 处理全海洋情况
if (ans == 0) return 1;
// 遍历海洋区域,寻找合并后的最大岛屿面积
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 0) {
HashSet<Integer> set = findNeighbor(grid, i, j); // 找到相邻岛屿
if (set.size() < 1) continue; // 若无相邻岛屿,则跳过
int t = 1;
for (Integer m : set) t += map.get(m); // 计算合并后的岛屿面积
ans = Math.max(ans, t); // 更新最大岛屿面积
}
}
}
return ans;
}
// 查找相邻的岛屿
public HashSet<Integer> findNeighbor(int[][] grid, int x, int y) {
HashSet<Integer> set = new HashSet<>();
if (!notarea(x - 1, y) && grid[x - 1][y] != 0) set.add(grid[x - 1][y]);
if (!notarea(x + 1, y) && grid[x + 1][y] != 0) set.add(grid[x + 1][y]);
if (!notarea(x, y - 1) && grid[x][y - 1] != 0) set.add(grid[x][y - 1]);
if (!notarea(x, y + 1) && grid[x][y + 1] != 0) set.add(grid[x][y + 1]);
return set;
}
// 标记岛屿并计算面积
public int land(int[][] grid, int x, int y, int index) {
if (notarea(x, y) || grid[x][y] == 0) return 0;
if (grid[x][y] != 1) return 0;
grid[x][y] = index;
int region = land(grid, x, y + 1, index) + land(grid, x, y - 1, index)
+ land(grid, x + 1, y, index) + land(grid, x - 1, y, index);
return region + 1;
}
// 判断是否超出边界
public boolean notarea(int x, int y) {
return x < 0 || y < 0 || x >= n || y >= n;
}
}
现在进步很大了,一般看完题解之后知道怎么做第二天再做一遍是能做出来的,不过代码会有点冗余,但能做出来就好了。下面这是我的第二遍自己做出来的
class Solution {
int n,m,ans;
Map<Integer, Integer> map = new HashMap<>();
public int largestIsland(int[][] grid) {
n = grid.length;
m = grid[0].length;
int index = 2;
for(int i = 0 ;i < n;i ++) { // 遍历陆地
for(int j =0 ;j < m;j ++) {
if(grid[i][j] == 1) {
int t = dfs(i,j,grid,index);
ans = Math.max(ans, t);
map.put(index, t);index ++;
}
}
}
for(int i = 0;i < n;i ++) {
for(int j = 0;j < m;j ++) {
if(grid[i][j] == 0) {
int regoin = findNeibor(i , j, grid);
ans = Math.max(ans, regoin + 1);
}
}
}
return ans;
}
public int findNeibor(int x, int y , int[][] grid) {
int te = 0;
Set<Integer> set = new HashSet<>();
if(!isArea(x + 1, y) && map.containsKey(grid[x + 1][y]) && !set.contains(grid[x + 1][y])) {
te += map.get(grid[x + 1][y]);
set.add(grid[x + 1][y]);
}
if(!isArea(x - 1, y) && map.containsKey(grid[x - 1][y]) && !set.contains(grid[x - 1][y])) {
te += map.get(grid[x - 1][y]);
set.add(grid[x - 1][y]);
}
if(!isArea(x, y + 1) && map.containsKey(grid[x][y + 1]) && !set.contains(grid[x][y + 1])) {
set.add(grid[x][y + 1]);
te += map.get(grid[x][y + 1]);
}
if(!isArea(x, y - 1) && map.containsKey(grid[x][y - 1]) && !set.contains(grid[x][y - 1])) {
set.add(grid[x][y - 1]);
te += map.get(grid[x][y - 1]);
}
grid[x][y] = -1;
return te;
}
public int dfs(int x, int y, int[][] grid, int index) {
if(isArea(x, y) || grid[x][y] != 1) return 0;
grid[x][y] = index;
return dfs(x + 1, y, grid, index) + dfs(x - 1, y, grid, index) +
dfs(x, y + 1, grid, index) + dfs(x, y - 1, grid, index) + 1;
}
public boolean isArea(int x, int y) {
if(x < 0 || y < 0 || x >= n || y >= m ) return true;
return false;
}
}