一、 代码题解
给定一个由 0 和 1 组成的非空二维数组 grid ,用来表示海洋岛屿地图。
一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。如果没有岛屿,则返回面积为 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
解释: 对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。
二、代码思路
本题属于图的遍历,图的遍历与树的遍历是类似的但是也是有区别的,树是没有环路的,而图是有环路的,所以在图的遍历时我们需要额外的数组去记录已经遍历过的节点。
同样的,图的遍历也有DFS和BFS,这两种遍历方式各有优势。
本题,毫无疑问需要使用BFS遍历,原因就是题目要求出每个岛屿的面积,而岛屿面积是相邻的数组块且数组块的值为1,因此我们使用BFS遍历正好。
BFS遍历就是利用了队列存放某一个模块相邻的所有模块,对应到此题目,就是相邻的所有区域。同时,别忘了这是图的遍历,所以一定要维护一个访问数组。
- 初始化访问数组。
- 利用bfs访问各个元素,并且维护一个队列。
- 如果某个元素为1,且没被访问过,就加入队列。
- 把该元素相邻的所有元素都加入该队列。
- 注意更新最大面积与访问数组即可。
三、 代码题解
class Solution {
//初始化方向数组
static int[][] directions= {{-1,0},{1,0},{0,1},{0,-1}};
public int maxAreaOfIsland(int[][] grid) {
//定义二维访问数组
int m = grid.length;
int n = grid[0].length;
boolean visited[][] = new boolean[m][n];
int maxArea = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//使用bfs遍历相邻位置
if (grid[i][j] != 1 || visited[i][j] != false) {
continue;
}
Queue<int[]> queue = new LinkedList<>();
int area = 0;
queue.offer(new int[]{i, j});
visited[i][j] = true;
while (!queue.isEmpty()) {
int []array = queue.poll();
area++;
int x = array[0];
int y = array[1];
for (int []arr : directions) {
int newX = x + arr[0];
int newY = y + arr[1];
if (newX >= 0 && newX < m && newY >= 0 && newY < n
&& grid[newX][newY] == 1 && visited[newX][newY] == false) {
queue.offer(new int[]{newX, newY});
visited[newX][newY] = true;
}
}
}
maxArea = Math.max(maxArea, area);
}
}
return maxArea;
}
}
时间复杂度:O(mn),其中 m 和 n 分别是矩阵 grid 的行数和列数。广度优先搜索最多需要访问每个元素一次。
空间复杂度:O(mn),其中 m 和 n 分别是矩阵 grid 的行数和列数。记录每个元素是否被访问过的二维数组和队列需要 O(mn) 的空间。