(图论) 827. 最大人工岛 ——【Leetcode每日一题】

❓ 827. 最大人工岛

难度:困难

给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1

返回执行此操作后,grid 中最大的岛屿面积是多少?

岛屿 由一组上、下、左、右四个方向相连的 1 形成。

示例 1:

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

示例 2:

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

示例 3:

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

提示

  • n == grid.length
  • n == grid[i].length
  • 1 <= n <= 500
  • grid[i][j]01

💡思路:

本题的一个暴力想法,应该是遍历地图尝试 将每一个 0 改成1,然后去搜索地图中的最大的岛屿面积。

本题使用 深搜 还是 广搜 都是可以的,其目的就是遍历岛屿做一个标记,相当于染色,那么使用哪个遍历方式都行,我用的是深搜。

根据暴力的想法每次深搜遍历计算最大岛屿面积,我们都做了很多重复的工作。只要用一次深搜把每个岛屿的面积记录下来就好。

  1. 一次遍历地图,得出各个岛屿的面积,并做编号记录。可以使用map 记录,key 为岛屿编号,value 为岛屿面积,我是直接在原 grid 上直接标记;
  2. 在遍历地图,遍历 0 的方格(因为要将 0 变成 1),并统计该1(由 0 变成的1)周边岛屿面积,将其相邻面积相加在一起,遍历所有 0 之后,就可以得出 选一个0变成1 之后的最大面积。

🍁代码:(C++、Java)

C++

class Solution {
private:int cnt;int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};void dfs(vector<vector<int>>& grid, int x, int y, int mark){if(grid[x][y] == 0 || grid[x][y] != 1) return; // 遇到海水或访问过的节点,则终止grid[x][y] = mark; //给陆地标记新的标签cnt++;for(int i = 0; i < 4; i++){int nextx = x + dir[i][0];int nexty = y + dir[i][1];if(nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;dfs(grid, nextx, nexty, mark);}}
public:int largestIsland(vector<vector<int>>& grid) {int m = grid.size(), n = grid[0].size();unordered_map<int, int> gridNum;int mark = 2;bool isAllGrid = true; // 标记是否整个地图都是陆地for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(grid[i][j] == 0) isAllGrid = false;if(grid[i][j] == 1){cnt = 0;dfs(grid, i, j, mark);gridNum[mark] = cnt;mark++;}}}if (isAllGrid) return n * m; // 如果都是陆地,返回全面积// 以下逻辑是根据添加陆地的位置,计算周边岛屿面积之和int ans = 0;unordered_set<int> visitedGrid;  // 标记访问过的岛屿for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){int num = 1;visitedGrid.clear(); // 每次使用时,清空if(grid[i][j] == 0){for(int k = 0; k < 4; k++){int neari = i + dir[k][0];int nearj = j + dir[k][1];if (neari < 0 || neari >= grid.size() || nearj < 0 || nearj >= grid[0].size()) continue;if (visitedGrid.count(grid[neari][nearj])) continue;// 把相邻四面的岛屿数量加起来num += gridNum[grid[neari][nearj]];visitedGrid.insert(grid[neari][nearj]); // 标记该岛屿已经添加}}ans = max(ans, num);}}return ans;}
};

Java

class Solution {private static final int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四个方向private int cnt;private void dfs(int[][] grid, int x, int y, int mark){if(grid[x][y] != 1) return;grid[x][y] = mark;cnt++;for(int i = 0; i < 4; i++){int nextx = x + dir[i][0];int nexty = y + dir[i][1];if(nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length) continue;dfs(grid, nextx, nexty, mark);}}public int largestIsland(int[][] grid) {int m = grid.length, n = grid[0].length;Map<Integer, Integer> gridNum = new HashMap<>();int mark = 2;boolean isAllGrid = true;for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(grid[i][j] == 0) isAllGrid = false;if(grid[i][j] == 1){cnt = 0;dfs(grid, i, j, mark);gridNum.put(mark++, cnt);}}}if(isAllGrid) return n * m;int ans = 0;for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){Set<Integer> hashSet = new HashSet<>();     // 防止同一个区域被重复计算int num = 1;if(grid[i][j] == 0){for(int k = 0; k < 4; k++){int neari = i + dir[k][0];int nearj = j + dir[k][1];if(neari < 0 || neari >= grid.length || nearj < 0 || nearj >= grid[0].length) continue;int curMark = grid[neari][nearj];     // 获取对应位置的标记if (hashSet.contains(curMark) || !gridNum.containsKey(curMark)) continue;num += gridNum.get(curMark);hashSet.add(curMark);}ans = Math.max(ans, num);}}}return ans;}
}

🚀 运行结果:

在这里插入图片描述

🕔 复杂度分析:

  • 时间复杂度 O ( m n ) O(mn) O(mn),其中 mngrid的高和宽。方格地图中,每个节点我们就遍历一次,并不会重复遍历。
  • 空间复杂度 O ( m n ) O(mn) O(mn)

题目来源:力扣。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我LeetCode主页 / CSDN—力扣专栏,每日更新!

注: 如有不足,欢迎指正!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/112384.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Maven 安装配置

Maven 安装配置 文章目录 Maven 安装配置一、下载 Maven二、解压Maven核心程序三、指定本地仓库四、配置阿里云镜像仓库4.1 将原有的例子配置注释掉4.2 加入新的配置 五、配置 Maven 工程的基础 JDK 版本六、配置环境变量6.1 检查 JAVAHOME 配置是否正确6.2 配置 MAVENHOME6.3 …

vue柱状图+折线图组合

<template><div id"main" style"width: 100%;height: 500px; padding-top: .6rem"></div> </template>data() {return {weekData: ["1周","2周","3周","4周","5周","6周&…

Java + Selenium + Appium自动化测试

一、启动测试机或者Android模拟器&#xff08;Genymotion俗称世界上最快的模拟器&#xff0c;可自行百度安装&#xff09; 二、启动Appium&#xff08;Appium环境安装可自行百度&#xff09; 三、安装应用到Genymotion上&#xff0c;如下图我安装一个计算机的小应用&#xff0c…

Python+Django前后端分离

程序示例精选 PythonDjango前后端分离 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《PythonDjango前后端分离》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与应…

Postman应用——Request数据导入导出

文章目录 导入请求数据导出请求数据导出Collection导出Environments 导出所有请求数据导出请求响应数据 Postman可以导入导出Request和Variable变量配置&#xff0c;可以通过文本方式&#xff08;JOSN文本&#xff09;或链接方式进行导入导出。 导入请求数据 可以通过JSON文件…

腾讯mini项目-【指标监控服务重构】2023-08-21

今日已办 PPT 汇报 答辩的时间需要把控人员的分配不够合理效果展示不够清晰&#xff0c;不够熟练重点的调研测试对比报告还未产出 项目待办 50字总结项目意义&#xff0c;top3 难点watermill 和 profile 正则处理otel-sdk 隐式&#xff0c;可扩展接入云 clickhouse 集群&am…

oracle创建表空间、用户、权限以及导入dmp文件

创建表空间 create tablespace A_DATA logging datafile F:\CODEAPP\ORACLE\ORADATA\A_DATA01.DBF size 50m autoextend on next 50m maxsize 32767m extent management local; -- 这个语句将创建一个大小为50MB的数据文件&#xff0c;启用自动扩展功能&#xff0c;每次扩展50…

pdf在线加密怎么做?几个好用的方法分享

PDF在线加密怎么做&#xff1f;在进行PDF在线加密时&#xff0c;您可以使用以下几种方法来确保文档的安全性&#xff0c;并注意以下一些加密的注意事项。 方法一&#xff1a;使用PDF转换加密工具 首先我们可以在电脑上打开迅捷PDF转换器工具&#xff0c;进入该转换工具后先在顶…

ChatGLM GPT原理介绍

图解GPT 除了BERT以外,另一个预训练模型GPT也给NLP领域带来了不少轰动,本节也对GPT做一个详细的讲解。 OpenAI提出的GPT-2模型(https://openai.com/blog/better-language-models/) 能够写出连贯并且高质量的文章,比之前语言模型效果好很多。GPT-2是基于Transformer搭建的,相…

基于虚拟仿真技术的汽车燃油泵控制

在当前激烈的竞争环境下&#xff0c;汽车行业正在加速产业和技术更迭&#xff0c;整车厂对大型ECU嵌入式控制系统和软件的需求迫在眉睫。 然而&#xff0c;复杂而庞大的汽车系统往往由多个物理系统组成&#xff0c;系统所对应的模型都需要在不同的领域实现&#xff1a;发动机、…

vue3+ts 实现移动端分页

current 开始页码 pageSize 结束页码 const sizeref<number>(10) //一页显示十条 const eachCurrentPageref<number>(1) //默认是第一页interface ITdata {current: number,pageSize: number,// xxxx 其他参数... } const selectApplyList ref<…

快速上手Linux基础开发工具

目录 软件包管理器 概念理解 用法示例 - 以yum为例 vim 模式的切换 常用操作 插件和配置 gcc/g gdb make / makefile 软件包管理器 概念理解 在Linux下安装软件的话&#xff0c;一个比较原始的办法是下载程序的源代码&#xff0c;然后进行编译&#xff0c;进而得到…