标签:优先 area int dfs length grid 搜索 区块 Leetcode
题目来源:https://leetcode-cn.com/problems/max-area-of-island/
解题思路原文:https://leetcode-cn.com/problems/max-area-of-island/solution/biao-zhun-javadong-tai-gui-hua-jie-fa-100-by-mark-/
题目
岛屿的最大面积
- 给你一个大小为 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
输入:grid = [[0,0,0,0,0,0,0,0]]
输出:0
提示
① m == grid.length
② n == grid[i].length
③ 1 <= m, n <= 50
④ grid[i][j] 为 0 或 1
解题思路
根据题意可立刻解读出题目含义:获取每个岛的面积,取最大面积返回。最容易想到的思路就是使用深度优先搜索DFS强行遍历每一个岛屿的所有区块。
要获取每个岛屿的面积,自然要遍历整个地图所有的区块,遇到了陆地便由陆地所在坐标向四周搜索附近的陆地并统计陆地的面积。但是遍历整个地图的话,自然会遇到这么一个情况——我们访问到陆地区块a1,然后根据a1消耗了时间资源获取了整个岛屿A的所有区块(a1,a2,a3,a4),然后继续遍历地图并访问到了a2,又一次的消耗了时间资源去获取我们已经获取的A岛区块。
对于这种情况,我们不难想到创建一个哈希表用来存储所有访问过的区块,这样一来,我们访问岛屿的时候,就会把整个岛屿的所有区块add岛哈希表中。以后在访问到陆地的时候,只需要先判断哈希表内是否contains这个区块就可以避免消耗资源去获取我们已经获取的区块信息了。
但是本题只需要求得岛屿的最大面积,大量的数据存储在哈希表中无疑会占用不必要的内存资源,我们会考虑到在获取岛的面积后,将哈希表相关内容清除掉,但这又会影响到我们创建哈希表的初衷(如果当前访问的区块已经被探索,则不再访问)。于是我们可以直接在地图上对探索过的岛屿进行处理。
处理方法:遇到陆地,搜索以陆地为起点的所有相连的陆地,统计岛屿总面积的同时,将岛屿转变成海洋。这样一来,岛屿的信息一旦被记录,就会从地图上消失,而随之带来的就是后续地图遍历不会扫描到任何被探索过的岛屿,大幅度的减少了内存资源的消耗。
思路示例:
首先是自定义一个地图,该地图只有一个岛屿,目的是展示如何根据一个陆地获取整个岛屿。
①从地图起点开始遍历,尝试碰到第一个陆地区块
②访问到陆地区块,设定岛屿面积为1,尝试访问四周区块,同时将自己变成海洋
③以此类推
从图中可看出,对每块陆地区块,递归探索他的四个方向区块,如果陆地便继续递归探索,最终可获得整个岛屿的面积。
定义一个max用来存储最大面积即可解决本题。
public int maxAreaOfIsland(int[][] grid) {
int maxArea = 0;
int height = grid.length;
int width = grid[0].length;
//判断每个区块是否为陆地
//如果是陆地那么在记录之后 将陆地变成海洋
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (grid[i][j] == 1) {
int area = dfs(i, j, grid);
if (area > maxArea)
//如果新岛屿面积更大,则替换
maxArea = area;
}
}
}
return maxArea;
}
public int dfs(int i, int j, int[][] grid) {
int height = grid.length;
int width = grid[0].length;
//执行本段函数的条件
// 1.区块的坐标合理
// 2.区块内容为陆地
//★尽管在maxArea函数中有明确提及只有陆地才能访问该函数,但是本函数会自行向四周搜索,要避免搜索到的海洋区块执行函数★
if (i < 0 || j < 0 ||
i >= height || j >= width ||
grid[i][j] == 0) {
return 0;
}
//执行到这一步说明该区块是陆地
//区块面积
int area = 1;
//将该区块转为海洋
grid[i][j]=0;
//向下搜索
area += dfs(i + 1, j, grid);
//向上搜索
area += dfs(i - 1, j, grid);
//向右搜索
area += dfs(i, j + 1, grid);
//向左搜索
area += dfs(i, j - 1, grid);
return area;
}
代码清爽版
public class max_area_of_island {
public int maxAreaOfIsland(int[][] grid) {
int maxArea = 0;
for (int i = 0; i < grid.length; i++)
for (int j = 0; j < grid[0].length; j++)
if (grid[i][j] == 1)
maxArea = Math.max(maxArea, dfs(i, j, grid));
return maxArea;
}
public int dfs(int i, int j, int[][] grid) {
if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == 0)
return 0;
int area = 1;
grid[i][j] = 0;
area += dfs(i + 1, j, grid);
area += dfs(i - 1, j, grid);
area += dfs(i, j + 1, grid);
area += dfs(i, j - 1, grid);
return area;
}
public static void main(String[] args) {
max_area_of_island demo = new max_area_of_island();
System.out.println(demo.maxAreaOfIsland(new int[][]{
{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}}
));
}
}
public class max_area_of_island {
public int maxAreaOfIsland(int[][] grid) {
int maxArea = 0;
for (int i = 0; i < grid.length; i++)
for (int j = 0; j < grid[0].length; j++)
if (grid[i][j] == 1)
maxArea = Math.max(maxArea, dfs(i, j, grid));
return maxArea;
}
public int dfs(int i, int j, int[][] grid) {
if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == 0)
return 0;
int area = 1;
grid[i][j] = 0;
area += dfs(i + 1, j, grid);
area += dfs(i - 1, j, grid);
area += dfs(i, j + 1, grid);
area += dfs(i, j - 1, grid);
return area;
}
public static void main(String[] args) {
max_area_of_island demo = new max_area_of_island();
System.out.println(demo.maxAreaOfIsland(new int[][]{
{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}}
));
}
}
执行用时:2 ms, 在所有 Java 提交中击败了 99.73%的用户
内存消耗:38.9 MB, 在所有 Java 提交中击败了 60.41%的用户
标签:优先,area,int,dfs,length,grid,搜索,区块,Leetcode 来源: https://blog.csdn.net/qq_24251607/article/details/122474704
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。