Leetcode(695)——岛屿的最大面积

题目

给你一个大小为 m × n m \times n m×n 的二进制矩阵 grid 。

岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

示例 1:


输入: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 。

示例 2:

输入:grid = [[0,0,0,0,0,0,0,0]]
输出:0

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 1 1 <= m, n <= 50 50 50
  • grid[i][j] 为 0 0 0 或 1 1 1

题解

方法一:DFS(递归写法)

思路

  • 我们想知道网格中每个连通形状的面积,然后取最大值。
  • 如果我们在一个土地上,以 4 4 4 个方向探索与之相连的每一个土地(以及与这些土地相连的土地),那么探索过的土地总数将是该连通形状的面积。
  • 为了确保每个土地访问不超过一次,我们每次经过一块土地时,将这块土地的值置为 0 0 0。这样我们就不会多次访问同一土地。

​​  这里我们使用了一个小技巧,对于四个方向的遍历,可以创造一个数组 [-1, 0, 1, 0, -1],每相邻两位即为上下左右四个方向之一。

​​  在辅函数里,一个一定要注意的点是辅函数内递归搜索时,边界条件的判定。边界判定一般有两种写法,一种是先判定是否越界,只有在合法的情况下才进行下一步搜索(即判断放在调用递归函数前);另一种是不管三七二十一先进行下一步搜索,待下一步搜索开始时再判断是否合法(即判断放在辅函数第一行)。我们这里分别展示这两种写法。

代码实现

Leetcode 官方题解:

class Solution {int dfs(vector<vector<int>>& grid, int cur_i, int cur_j) {if (cur_i < 0 || cur_j < 0 || cur_i == grid.size() || cur_j == grid[0].size() || grid[cur_i][cur_j] != 1) {return 0;}grid[cur_i][cur_j] = 0;int di[4] = {0, 0, 1, -1};int dj[4] = {1, -1, 0, 0};int ans = 1;for (int index = 0; index != 4; ++index) {int next_i = cur_i + di[index], next_j = cur_j + dj[index];ans += dfs(grid, next_i, next_j);}return ans;}
public:int maxAreaOfIsland(vector<vector<int>>& grid) {int ans = 0;for (int i = 0; i != grid.size(); ++i) {for (int j = 0; j != grid[0].size(); ++j) {ans = max(ans, dfs(grid, i, j));}}return ans;}
};

我自己的:

class Solution {void DFS(vector<vector<int>>& grid, int x, int y, int& area){if(0 > x || x >= grid[0].size() || y >= grid.size() || 0 > y) return;if(grid[y][x] == 1){// 上下左右area += 1;grid[y][x] = 0; // 置为0防止再次访问该点DFS(grid, x-1, y, area);DFS(grid, x+1, y, area);DFS(grid, x, y-1, area);DFS(grid, x, y+1, area);}}
public:int maxAreaOfIsland(vector<vector<int>>& grid) {int ans = 0, area, yn = grid.size(), xn = grid[0].size();for(int y = 0; y < yn; y++){for(int x = 0; x < xn; x++){if(grid[y][x] == 1){area = 0;DFS(grid, x, y, area);ans = ans < area? area: ans;}}}return ans;}
};

复杂度分析

时间复杂度: O ( m × n ) O(m×n) O(m×n)。其中 m m m 是给定网格中的行数, n n n 是列数。我们访问每个原本为1的网格最多一次。
空间复杂度: O ( m × n ) O(m \times n) O(m×n),递归的深度最大可能是整个网格的大小,因此最大可能使用 O ( m × n ) O(m \times n) O(m×n) 的栈空间。

方法二:DFS + 辅助栈(迭代写法)

思路

​​  原理与方法一相同,只是实现方式采用了迭代而不是递归,并使用栈辅助实现。

  • 方法一通过函数的调用来表示接下来想要遍历哪些土地,让下一层函数来访问这些土地。而方法二把接下来想要遍历的土地放在栈里,然后在取出这些土地的时候访问它们。
  • 访问每一片土地时,我们将对围绕它四个方向进行探索,找到还未访问的土地,加入到栈 stack \textit{stack} stack 中;
  • 另外,只要栈 stack \textit{stack} stack 不为空,就说明我们还有土地待访问,那么就从栈中取出一个元素并访问。

代码实现

Leetcode 官方题解:

class Solution {public:int maxAreaOfIsland(vector<vector<int>>& grid) {int ans = 0;for (int i = 0; i != grid.size(); ++i) {for (int j = 0; j != grid[0].size(); ++j) {int cur = 0;stack<int> stacki;stack<int> stackj;stacki.push(i);stackj.push(j);while (!stacki.empty()) {int cur_i = stacki.top(), cur_j = stackj.top();stacki.pop();stackj.pop();if (cur_i < 0 || cur_j < 0 || cur_i == grid.size() || cur_j == grid[0].size() || grid[cur_i][cur_j] != 1) {continue;}++cur;grid[cur_i][cur_j] = 0;int di[4] = {0, 0, 1, -1};int dj[4] = {1, -1, 0, 0};for (int index = 0; index != 4; ++index) {int next_i = cur_i + di[index], next_j = cur_j + dj[index];stacki.push(next_i);stackj.push(next_j);}}ans = max(ans, cur);}}return ans;}
};

我自己的:

class Solution {public:int maxAreaOfIsland(vector<vector<int>>& grid) {int ans = 0, area, yn = grid.size(), xn = grid[0].size();stack<pair<int, int>> island;pair<int, int> tmp;for(int y = 0; y < yn; y++){for(int x = 0; x < xn; x++){if(grid[y][x] == 1){area = 0;island.push(make_pair(y, x));while(!island.empty()){tmp.first = island.top().first;tmp.second = island.top().second;island.pop();if(grid[tmp.first][tmp.second] != 1) continue;grid[tmp.first][tmp.second] = 0;area++;if(tmp.second-1 >= 0) island.push(make_pair(tmp.first, tmp.second-1));if(tmp.second+1 < xn) island.push(make_pair(tmp.first, tmp.second+1));if(tmp.first-1 >= 0) island.push(make_pair(tmp.first-1, tmp.second));if(tmp.first+1 < yn) island.push(make_pair(tmp.first+1, tmp.second));}ans = max(area, ans);}}}return ans;}
};

复杂度分析

时间复杂度: O ( m × n ) O(m \times n) O(m×n)。其中 m m m 是给定网格中的行数, n n n 是列数。我们访问每个原本为1的网格最多一次。
空间复杂度: O ( m × n ) O(m \times n) O(m×n),栈中最多会存放所有的土地,土地的数量最多为 m × n m \times n m×n 块,因此使用的空间为 O ( m × n ) O(m \times n) O(m×n)。

方法三:BFS + 队列

思路

​​  把方法二中的栈改为队列,每次从队首取出土地,并将接下来想要遍历的土地放在队尾,就实现了广度优先搜索算法。

代码实现

Leetcode 官方题解:

class Solution {public:int maxAreaOfIsland(vector<vector<int>>& grid) {int ans = 0;for (int i = 0; i != grid.size(); ++i) {for (int j = 0; j != grid[0].size(); ++j) {int cur = 0;queue<int> queuei;queue<int> queuej;queuei.push(i);queuej.push(j);while (!queuei.empty()) {int cur_i = queuei.front(), cur_j = queuej.front();queuei.pop();queuej.pop();if (cur_i < 0 || cur_j < 0 || cur_i == grid.size() || cur_j == grid[0].size() || grid[cur_i][cur_j] != 1)continue;++cur;grid[cur_i][cur_j] = 0;int di[4] = {0, 0, 1, -1};int dj[4] = {1, -1, 0, 0};for (int index = 0; index != 4; ++index) {int next_i = cur_i + di[index], next_j = cur_j + dj[index];queuei.push(next_i);queuej.push(next_j);}}ans = max(ans, cur);}}return ans;}
};

我自己的:

class Solution {public:int maxAreaOfIsland(vector<vector<int>>& grid) {int ans = 0, area, yn = grid.size(), xn = grid[0].size();queue<pair<int, int>> island;pair<int, int> tmp;for(int y = 0; y < yn; y++){for(int x = 0; x < xn; x++){if(grid[y][x] == 1){area = 0;island.push(make_pair(y, x));while(!island.empty()){tmp.first = island.front().first;tmp.second = island.front().second;island.pop();if(grid[tmp.first][tmp.second] != 1) continue;grid[tmp.first][tmp.second] = 0;area++;if(tmp.second-1 >= 0) island.push(make_pair(tmp.first, tmp.second-1));if(tmp.second+1 < xn) island.push(make_pair(tmp.first, tmp.second+1));if(tmp.first-1 >= 0) island.push(make_pair(tmp.first-1, tmp.second));if(tmp.first+1 < yn) island.push(make_pair(tmp.first+1, tmp.second));}ans = max(area, ans);}}}return ans;}
};

复杂度分析

时间复杂度: O ( m × n ) O(m×n) O(m×n)。其中 m m m 是给定网格中的行数, n n n 是列数。我们访问每个原本为1的网格最多一次。
空间复杂度: O ( m × n ) O(m \times n) O(m×n),队列中最多会存放所有的土地,土地的数量最多为 m × n m \times n m×n 块,因此使用的空间为 O ( m × n ) O(m \times n) O(m×n)。

Leetcode(695)——岛屿的最大面积相关推荐

  1. LeetCode 695.岛屿的最大面积

    LeetCode 695.岛屿的最大面积 给你一个大小为 m x n 的二进制矩阵 grid . 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的 ...

  2. LeetCode 695. 岛屿的最大面积【c++/java详细题解】

    目录 1.题目 2.思路 3.c++代码 4.java代码 1.题目 给定一个包含了一些 0 和 1 的非空二维数组 grid . 一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相 ...

  3. LeetCode 695. 岛屿的最大面积(图的BFS/DFS)

    文章目录 1. 题目 2. 解题 2.1 BFS广度优先搜索 2.2 DFS深度优先搜索 1. 题目 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直 ...

  4. LeetCode 695. 岛屿的最大面积

    文章目录 题目 题解 代码 题目 给定一个包含了一些 0 和 1 的非空二维数组 grid . 一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直 ...

  5. LeetCode 695 岛屿的最大面积

    题目描述 给定一个包含了一些 0 和 1 的非空二维数组 grid .一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平 或者竖直方向上相邻.你可以假设 ...

  6. leetcode 695. 岛屿的最大面积 python

    题目描述: 输入的grid是一个数组,其中0代表海洋,1代表岛屿,题目要求寻找最大岛屿面积,即寻找grid中连续1的最大值. 题解: 采用深度优先搜索dfs的方法: 1.对位置[i,j],如果i j超 ...

  7. 力扣(Leetcode)695. 岛屿的最大面积(Java)带注释

    leetcode刷题695. 岛屿的最大面积 1.题目描述 2.解法 1.DFS(深度优先搜索) 2.DFS + 栈 1.题目描述 给你一个大小为 m x n 的二进制矩阵 grid . 岛屿 是由一 ...

  8. 每日一道leetcode(python)695. 岛屿的最大面积

    每日一道leetcode(python)695. 岛屿的最大面积 2021-08-21 给定一个包含了一些 0 和 1 的非空二维数组 grid .一个 岛屿 是由一些相邻的 1 (代表土地) 构成的 ...

  9. 岛屿问题 通用解-463.岛屿周长-200.岛屿数量-695.岛屿的最大面积-827.最大人工岛

    文章目录 岛屿问题 如何在网格上做DFS(通用解) 463.岛屿的周长 题目 题解 -通用模板 题解2 200.岛屿数量 题目 题解 695.岛屿的最大面积 题目 题解 827.最大人工岛 题目 题解 ...

  10. 岛屿类-网格类问题-DFS | 力扣695. 岛屿的最大面积

    思路参考上文: 岛屿类-网格类问题-DFS | 力扣200. 岛屿数量 本文讲解695. 岛屿的最大面积问题,属于常见的岛屿类-网格类问题 本题使用DFS的思想 题目 给定一个包含了一些 0 和 1 ...

最新文章

  1. 3.5.2 ALOHA协议
  2. 单臂路由实验-VTP
  3. 为什么要用相对论为GPS导航提供修正
  4. 可以使任何人获得管理员权限的Windows 10系统漏洞
  5. warning: pointer of type 'void *' used in arithmetic
  6. linux cfs调度器_模型实现
  7. java简历项目经验大全(java商城项目经验简历)
  8. c语言字符幂函数怎么编写,c语言幂函数(c语言中如何编写幂函数)
  9. mediawiki java api_MediaWiki API 帮助
  10. UI设计--蓝湖切图
  11. 很开心你能来,不遗憾你走开
  12. 计算机学院考勤管理办法,学生考勤管理规定
  13. 更换SSD系统盘-PE重装系统
  14. 天玑800u处理器怎么样,相当于骁龙的多少
  15. 已解决(Python语法报错)SyntaxError: invalid syntax
  16. wx.showModal(模态框)的相关设置
  17. 修改Chem 3D模型的化学键属性的方法有哪些
  18. Unresolved reference ‘sklearn‘问题|scikit-learn包安装
  19. DSPE-PEG-GE11,磷脂-聚乙二醇-肿瘤细胞表皮生长因子肽GE11
  20. 快手2020校园招聘秋招笔试--算法B试卷

热门文章

  1. 利用双栈法实现简易计算器
  2. 【个人记录】如何使用PhotoShop(PS),Labelme和Labelimg做数据集标注
  3. 一、JDK、JRE、JVM的区别
  4. python数学编程_用Python编程解决数学问题
  5. 网易云课堂python怎样_网易云课堂开设的计算机专业课程怎么样?结业后能达到什么水平?...
  6. 物联网与移动宽带——未来5G的两大着眼点
  7. 特殊符号 UNICODE编码
  8. 试着使用SDL2复刻曹操传(一)
  9. SimpleDateFormat--时间处理
  10. Serverless架构用这5大优势,挽救了后来7亿用户的Instagram