题目描述

在二维地图上, 0 代表海洋, 1 代表陆地,我们最多只能将一格 0 海洋变成 1 变成陆地。

进行填海之后,地图上最大的岛屿面积是多少?(上、下、左、右四个方向相连的 1 可形成岛屿)

示例1

        输入:
[[1, 0], [0, 1]]
输出:
3
解释:
将一格 0 变成 1 ,最终连通两个小岛得到面积为 3 的岛屿。

示例2

        输入:
[[1, 1], [1, 0]]
输出:
4
解释:
将一格 0 变成 1 ,岛屿的面积扩大为 4 。

示例3

        输入:
[[1, 1], [1, 1]]
输出:
4
解释:
没有 0 可以让我们变成 1 ,面积依然为 4 。

提示

  • 1 <= grid.length = grid[0].length <= 50
  • 0 <= grid[i][j] <= 1

题解

没有做过这种类型题目的强烈建议自己动手实现一遍,对提升代码能力有很大帮助。

这题虽然是 hard 难度,但其实没有什么算法,只用到了 dfs 求连通块而已。我们只需要知道填充了一个 0 之后,它上下左右跟它相邻的 4 块连通块是多大。

首先普及一下什么是连通块,就是一块由 1 组成的区域,其中任意两块 1 都可以由一条 1 组成的路径走过去(只能上下左右走)。那么这题我们遍历所有的 0 ,把它四周的连通块大小加起来就是填充了这块 0 之后的连通块大小了。那么问题是怎么知道它周围连通块的大小呢?

首先我们得求出所有连通块的大小,然后存下来,这就得用到 dfs 了。

用二维数组 index (初始化为 -1)记录方块是否被搜索过。然后遍历所有的方块,如果是 1 ,并且 index 为 -1 (也就是没被搜索过),那么它的 index 设为 1 ,表示被搜索过了。然后从它开始向四周进行 dfs ,直到跟它相连的所有 1 的连通块都被搜索完毕。这时候整块连通块里面的 1 方块的 index 都被设成了 1 ,就算以后被遍历到了也不会被搜索了。那么大小怎么记录呢?只需要设置一个变量 cnt 初始为 1 ,然后 dfs 的时候遇到一个未被搜索的块就加 1 ,最后 cnt 就是当前连通块的大小了。

光知道了每个连通块的大小还不行,对于一个 0 块,四周的 1 方块万一属于同一个连通块怎么办?得区分它们,不然就会被重复计算。所以在上面的 dfs 之前,给那块连通块一个唯一的编号(从 0 开始),遇到下一个连通块就加 1 。这样 index 数组就可以用来存连通块的编号了,同时还能表示方块是否被搜索过。

具体的细节还得看代码,有很多实现的技巧,当然我写的还有一些优化余地。

代码

c++

        class Solution {public:static const int N = 55;int dx[4] = {0, 0, 1, -1};int dy[4] = {1, -1, 0, 0};int index[N][N], area[N*N], flag[N*N];int m, n;int largestIsland(vector<vector<int>>& grid) {m = grid.size();n = grid[0].size();memset(index, -1, sizeof index);memset(area, 0, sizeof area);memset(flag, 0, sizeof flag);int res = 0, idx = -1;for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {if (grid[i][j] == 1 && index[i][j] == -1) {int cnt = 1;index[i][j] = ++idx;dfs(i, j, idx, cnt, grid);area[idx] = cnt;res = max(res, cnt);}}}for (int x = 0; x < m; ++x) {for (int y = 0; y < n; ++y) {if (grid[x][y] == 0) {int tmp = 1;for (int i = 0; i < 4; ++i) {int nx = x + dx[i], ny = y + dy[i];if (inside(nx, ny) && grid[nx][ny] == 1 && !flag[index[nx][ny]]) {flag[index[nx][ny]] = 1;tmp += area[index[nx][ny]];}}for (int i = 0; i < 4; ++i) {int nx = x + dx[i], ny = y + dy[i];if (inside(nx, ny) && grid[nx][ny] == 1 && flag[index[nx][ny]]) {flag[index[nx][ny]] = 0;}}res = max(res, tmp);}}}return res;}bool inside(int x, int y) {return 0 <= x && x < m && 0 <= y && y < n;}void dfs(int x, int y, int idx, int& cnt, vector<vector<int>>& grid) {for (int i = 0; i < 4; ++i) {int nx = x + dx[i], ny = y + dy[i];if (inside(nx, ny) && grid[nx][ny] == 1 && index[nx][ny] == -1) {index[nx][ny] = idx;dfs(nx, ny, idx, ++cnt, grid);}}}
};

后记

dfs 求连通块是常规操作,必须要学会,很考验代码功底,要细心,不然很容易写错。

每日算法系列【LeetCode 827】最大人工岛相关推荐

  1. 重复次数最多的 子串_每日算法系列【LeetCode 424】替换后的最长重复字符

    题目描述 给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次.在执行上述操作后,找到包含重复字母的最长子串的长度. 示例1 输入: s = &quo ...

  2. Leetcode 827. 最大人工岛 C++

    Leetcode 827. 最大人工岛 题目 在二维地图上, 0代表海洋, 1代表陆地,我们最多只能将一格 0 海洋变成 1变成陆地. 进行填海之后,地图上最大的岛屿面积是多少?(上.下.左.右四个方 ...

  3. Leetcode 827.最大人工岛(Making A Large Island)

    Leetcode 827.最大人工岛 1 题目描述(Leetcode题目链接)   在二维地图上, 0代表海洋, 1代表陆地,我们最多只能将一格 0 海洋变成 1变成陆地. 进行填海之后,地图上最大的 ...

  4. Java实现 LeetCode 827 最大人工岛(DFS+暴力模拟)

    827. 最大人工岛 在二维地图上, 0代表海洋, 1代表陆地,我们最多只能将一格 0 海洋变成 1变成陆地. 进行填海之后,地图上最大的岛屿面积是多少?(上.下.左.右四个方向相连的 1 可形成岛屿 ...

  5. 求栈中元素个数算法_每日算法系列【LeetCode 315】计算右侧小于当前元素的个数...

    题目描述 给定一个整数数组 nums ,按要求返回一个新数组 counts .数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量. 示例 ...

  6. 数组最大可以开多大_每日算法系列【LeetCode 689】三个无重叠子数组的最大和

    题目描述 给定数组 由正整数组成,找到三个互不重叠的子数组的最大和. 每个子数组的长度为 ,我们要使这 个项的和最大化. 返回每个区间起始索引的列表(索引从 0 开始).如果有多个结果,返回字典序最小 ...

  7. 如何表示数组所有数都不等于一个数_每日算法系列【LeetCode 523】连续的子数组和...

    题目描述 给定一个包含非负数的数组和一个目标整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数. 示例1 输入: [ ...

  8. 如何表示数组所有数都不等于一个数_每日算法系列【LeetCode 330】按要求补齐数组...

    题目描述 给定一个已排序的正整数数组 nums ,和一个正整数 n .从 [1, n] 区间内选取任意个数字补充到 nums 中,使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的 ...

  9. 序列复杂度怎么看_每日算法系列【LeetCode 376】摆动序列

    题目描述 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5] 是一个 ...

  10. 找出最具竞争力的子序列_每日算法系列【LeetCode 376】摆动序列

    题目描述 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5] 是一个 ...

最新文章

  1. 网络连接、路由配置等
  2. python生成柱状图 不显示_python – Matplotlib图表不显示在PyCharm中
  3. Flutter学习记录(三、Flutter项目学习navBar的使用)
  4. Oracle 存储过程入门
  5. VTK读取序列化图像
  6. 系统架构师学习笔记-面向对象方法
  7. Mongodb2.6升级到Mongodb3.0.2笔记
  8. 新疆师范大学计算机研究生值得读吗,研究生还值得读吗
  9. 课时46:魔法方法:描述符(property的原理)
  10. 什么是基金转换?转换费用如何收取?
  11. DXperience 7.1.1
  12. 文本密度 php,基于最大文本密度的网页正文抽取方法
  13. 全球国家和地区代码列表
  14. Froala editor 2.9.5 使用
  15. 关于广告系统的定向,看这篇就够了
  16. 一张图解释什么是遗传算法_通俗易懂地解释遗传算法
  17. 迷宫问题的求解(广度和深度优先搜索)
  18. 微信支付的支付金额计算
  19. 清除数据库中所有数据
  20. 在Qt的公式计算中输入常量数值时的注意点

热门文章

  1. 【代码笔记】iOS-判断中英文混合的字符长度的两种方法
  2. (转)LIB和DLL的区别与使用
  3. [转]C++日志系统log4cxx使用总结
  4. 悲剧,当用cywin 写Linux脚本
  5. winform(C#)拖拽实现获得文件路径
  6. ehlib的DBGridEh控件中使用过滤功能的方法
  7. 防火墙、WAF、IPS、IDS都是什么
  8. python 操作mysql
  9. 使用Canvas基于手势可以使树秋千
  10. 游戏设计亦或课件设计