题目要求
原题目链接:695. 岛屿的最大面积
题目要求如下:
给你一个大小为 m x n 的二进制矩阵 grid 。
岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
岛屿的面积是岛上值为 1 的单元格的数目。
计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。
示例如下:
输入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出:6
解释:答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 。
解法1:深度优先搜索
思路
题目目的是求出网格中每块连通的面积,之后找出所有"岛屿"中面积最大的,并返回面积值。
那么我们只需要对网格|二维数组进行遍历,每次遍历到值为1的点时用计数器记录,并调用方法进行判断,寻找该点上下左右四个方向的点是否也为1,为1则计数器记录,同时再调用方法向下寻找四个方向的点并判断,以此类推。
为了避免数组内的点被重复访问,在记录过某一点面积后将该点的值修改为0即可,同时在代码书写过程中要注意边界情况处理。
完整AC代码
class Solution {
// 定义两个数组 组合后与点坐标相加 可以得到点周围四个方向点的坐标
int[] x = {0, 1, 0, -1};
int[] y = {-1, 0, 1, 0};
public int maxAreaOfIsland(int[][] grid) {
int ans = 0;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j <grid[0].length; j++){
// 每次都只记录最大面积
ans = Math.max(ans, dfs(grid, i, j));
}
}
return ans;
}
public int dfs(int[][]grid, int cx, int cy){
// 边界条件判断 以及01判断
if(cx < 0 || cy < 0 || cx >= grid.length || cy >= grid[0].length || grid[cx][cy] == 0) return 0;
int ans = 1;
// 访问过的点不应该再次被访问 设为0避免重复访问
grid[cx][cy] = 0;
// 当前点的四个方向遍历 此处不需要判断坐标合规 因为df方法会判断
for(int i = 0; i < 4; i++){
ans += dfs(grid, cx + x[i], cy + y[i]);
}
return ans;
}
}
复杂度分析
时间复杂度:O(R × C),其中R和C分别表示给定网格行列,网格中的每个点最多访问一次,故时间复杂度O(R × C)。
空间复杂度:O(R × C),判断并记录岛屿面积时需要递归,递归深度最坏的情况是整个二维数组值都为1,即需要整个网格递归,因此空间复杂度为O(R × C)。
解法2:广度优先搜索
思路
与DFS思路基本相同,唯一的区别在于DFS在取到一个点的值为1时,立即递归调用判断下一个点,直到某一个点四周点的值全部为0时才开始记录面积。而bfs在取到一个点的值为1时,先将四周的点加入到一个队列中(放到队尾),不立即进行四周点的判断记录工作,而是在完成自己的面积记录后才执行四周的点判断。
完整AC代码
class Solution {
int[] x = {0, 1, 0, -1};
int[] y = {-1, 0, 1, 0};
public int maxAreaOfIsland(int[][] grid) {
int ans = 0;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j <grid[0].length; j++){
int cnt = 0;
Queue<Integer> qx = new LinkedList<Integer>();
Queue<Integer> qy = new LinkedList<Integer>();
qx.offer(i);
qy.offer(j);
while(!qx.isEmpty()){
int cx = qx.poll();
int cy = qy.poll();
if(cx < 0 || cy < 0 || cx >= grid.length || cy >= grid[0].length || grid[cx][cy] == 0) continue;
cnt++;
grid[cx][cy] = 0;
for(int k = 0; k < 4; k++){
qx.offer(cx + x[k]);
qy.offer(cy + y[k]);
}
}
ans = Math.max(ans, cnt);
}
}
return ans;
}
}
复杂度分析
时间复杂度:O(R × C),与DFS相同,其中R和C分别表示给定网格行列,网格中的每个点最多访问一次,故时间复杂度O(R × C)。
空间复杂度:O(R × C),需要额外的队列存放所有值为1的点,最坏的情况为R × C个点需要存储,故时间复杂度O(R × C)。