news 2026/3/2 21:49:20

算法题 最大人工岛

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 最大人工岛

827. 最大人工岛

问题描述

给你一个大小为n x n的二进制矩阵grid,其中0表示海洋,1表示陆地。

你可以将恰好一个海洋格子(即0)变为陆地(即1)。

返回执行此操作后,矩阵中最大岛屿面积。岛屿是由 4 个方向上相连的1形成的。

示例

输入:grid=[[1,0],[0,1]]输出:3解释:将 grid[0][1]变为1,可形成面积为3的岛屿。
输入:grid=[[1,1],[1,0]]输出:4解释:将 grid[1][0]变为1,整个矩阵变成一个面积为4的岛屿。
输入:grid=[[1,1],[1,1]]输出:4解释:矩阵中已经没有海洋格子,最大岛屿面积为4

算法思路

岛屿编号标记

  1. 遍历所有陆地,计算每个独立岛屿的面积

    • 使用 DFS/BFS 遍历每个未访问的陆地格子
    • 为每个岛屿分配唯一的编号(从 2 开始,避免与原始的 0、1 冲突)
    • 记录每个编号对应的岛屿面积
  2. 遍历所有海洋格子,模拟填海操作

    • 对于每个海洋格子 (0),检查其四个方向相邻的岛屿
    • 使用 Set 去重,避免重复计算同一个岛屿
    • 计算填海后可能形成的最大岛屿面积(1 + 所有相邻不同岛屿面积之和)
  3. 边界情况处理

    • 如果矩阵中全是陆地,直接返回总面积
    • 如果矩阵中全是海洋,返回 1(填一个格子)

代码实现

classSolution{// 方向数组:上下左右四个方向privatestaticfinalint[][]DIRECTIONS={{-1,0},{1,0},{0,-1},{0,1}};/** * 计算将一个海洋格子变为陆地后的最大岛屿面积 * * @param grid n x n 的二进制矩阵,0表示海洋,1表示陆地 * @return 最大岛屿面积 */publicintlargestIsland(int[][]grid){intn=grid.length;// 岛屿编号从2开始(避免与原始的0、1冲突)intislandId=2;// 记录每个岛屿编号对应的面积Map<Integer,Integer>islandArea=newHashMap<>();// 遍历所有格子,识别并标记所有岛屿for(inti=0;i<n;i++){for(intj=0;j<n;j++){// 如果当前格子是陆地(值为1),开始DFS计算岛屿面积if(grid[i][j]==1){intarea=dfs(grid,i,j,islandId);islandArea.put(islandId,area);islandId++;// 为下一个岛屿准备新的编号}}}// 初始化结果为当前最大岛屿面积(不进行填海操作的情况)intmaxArea=0;for(intarea:islandArea.values()){maxArea=Math.max(maxArea,area);}// 遍历所有海洋格子,模拟填海操作for(inti=0;i<n;i++){for(intj=0;j<n;j++){// 只处理海洋格子(值为0)if(grid[i][j]==0){// 使用Set记录相邻的不同岛屿编号,避免重复计算Set<Integer>neighborIslands=newHashSet<>();// 检查四个方向的相邻格子for(int[]dir:DIRECTIONS){intni=i+dir[0];intnj=j+dir[1];// 检查边界条件if(ni>=0&&ni<n&&nj>=0&&nj<n){// 如果相邻格子是陆地(编号>=2),加入Setif(grid[ni][nj]>=2){neighborIslands.add(grid[ni][nj]);}}}// 计算填海后的总面积:1(新填的格子)+ 所有相邻岛屿面积之和inttotalArea=1;for(intid:neighborIslands){totalArea+=islandArea.get(id);}maxArea=Math.max(maxArea,totalArea);}}}returnmaxArea;}/** * 深度优先搜索,计算岛屿面积并标记岛屿编号 * * @param grid 网格矩阵 * @param row 当前行坐标 * @param col 当前列坐标 * @param islandId 当前岛屿的编号 * @return 岛屿的面积 */privateintdfs(int[][]grid,introw,intcol,intislandId){intn=grid.length;// 边界检查:超出边界或不是陆地(原始值为1)if(row<0||row>=n||col<0||col>=n||grid[row][col]!=1){return0;}// 标记当前格子为当前岛屿编号grid[row][col]=islandId;// 初始化面积为1(当前格子)intarea=1;// 递归遍历四个方向的相邻格子for(int[]dir:DIRECTIONS){area+=dfs(grid,row+dir[0],col+dir[1],islandId);}returnarea;}}

算法分析

  • 时间复杂度:O(n²)
    • 每个格子最多被访问一次进行DFS,总时间复杂度 O(n²)
    • 遍历所有海洋格子,每个格子检查4个邻居,总时间复杂度 O(n²)
  • 空间复杂度:O(n²)
    • 岛屿面积映射表最多存储 O(n²) 个岛屿信息
    • DFS递归栈深度最坏情况下为 O(n²)
    • Set临时存储最多4个相邻岛屿编号,空间为 O(1)

算法过程

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

岛屿识别和标记

  1. 格子(0,0):值为1,开始DFS

    • 标记为岛屿2,面积=1
    • grid变为:[[2,0],[0,1]]
  2. 格子(1,1):值为1,开始DFS

    • 标记为岛屿3,面积=1
    • grid变为:[[2,0],[0,3]]
  3. 岛屿面积映射:{2: 1, 3: 1}

模拟填海

  1. 格子(0,1):海洋格子

    • 上:无,下:grid[1][1]=3,左:grid[0][0]=2,右:无
    • 相邻岛屿:{2, 3}
    • 总面积:1 + 1 + 1 = 3
  2. 格子(1,0):海洋格子

    • 上:grid[0][0]=2,下:无,左:无,右:grid[1][1]=3
    • 相邻岛屿:{2, 3}
    • 总面积:1 + 1 + 1 = 3

结果

  • 初始最大面积:1
  • 填海后最大面积:3
  • 返回结果:3

测试用例

publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:对角线岛屿int[][]grid1={{1,0},{0,1}};System.out.println("Test 1: "+solution.largestIsland(grid1));// 3// 测试用例2:三格陆地一格海洋int[][]grid2={{1,1},{1,0}};System.out.println("Test 2: "+solution.largestIsland(grid2));// 4// 测试用例3:全陆地int[][]grid3={{1,1},{1,1}};System.out.println("Test 3: "+solution.largestIsland(grid3));// 4// 测试用例4:全海洋int[][]grid4={{0,0},{0,0}};System.out.println("Test 4: "+solution.largestIsland(grid4));// 1// 测试用例5:复杂情况int[][]grid5={{1,0,1},{0,0,0},{1,0,1}};System.out.println("Test 5: "+solution.largestIsland(grid5));// 5// 测试用例6:单格int[][]grid6={{0}};System.out.println("Test 6: "+solution.largestIsland(grid6));// 1int[][]grid7={{1}};System.out.println("Test 7: "+solution.largestIsland(grid7));// 1// 测试用例8:大岛屿int[][]grid8={{0,0,0,0,0,0,0},{0,1,1,1,1,0,0},{0,1,0,0,1,0,0},{0,1,0,0,1,0,0},{0,1,1,1,1,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}};System.out.println("Test 8: "+solution.largestIsland(grid8));// 17}

关键点

  1. 岛屿编号

    • 使用 ≥2 的编号标记不同岛屿,避免与原始数据冲突
    • 编号本身作为岛屿的唯一标识符
  2. 去重处理

    • 使用 Set 存储相邻岛屿编号,防止同一岛屿被重复计算
  3. 边界情况

    • 全陆地:直接返回总面积
    • 全海洋:返回1(填一个格子的最小面积)
    • 单格矩阵:根据值返回1

常见问题

  1. 为什么岛屿编号从2开始?
    原始矩阵中只有0(海洋)和1(陆地),使用≥2的编号可以清楚区分哪些是原始陆地,哪些是已标记的岛屿。

  2. 为什么需要Set去重?
    岛屿形状如"U"形,海洋格子可能被同一个岛屿从多个方向包围,如果不使用Set去重,会重复计算同一个岛屿的面积。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/1 3:27:32

低代码平台怎么选?这5款免费方案很友好

概述这两年不管是做业务系统、内部工具&#xff0c;还是想推进企业数字化&#xff0c;低代码平台真的帮了大忙。实际用下来会发现&#xff0c;选对平台&#xff0c;很多原本要排期开发的事情&#xff0c;用配置就能解决&#xff0c;而且成本压力也小很多。这里结合自己和身边朋…

作者头像 李华
网站建设 2026/2/24 22:25:04

HTML DOM 元素

HTML DOM 元素 HTML DOM(文档对象模型)是现代网页设计的基础。DOM 将 HTML 文档解析为一个树状结构,使得开发者能够通过编程方式操作网页内容、样式和行为。本文将深入探讨 HTML DOM 元素的概念、结构和用途。 概念 DOM(Document Object Model)是一种跨平台和语言独立的…

作者头像 李华
网站建设 2026/2/26 4:59:50

基于springboot+vue的微信小程序的公开课管理系统(源码+lw+部署文档+讲解等)

课题介绍随着在线教育的蓬勃发展&#xff0c;公开课因优质教育资源共享的特性备受青睐&#xff0c;但传统公开课管理模式存在课程信息分散、报名流程繁琐、学习进度难追踪、师生互动不便捷等痛点&#xff0c;影响教学效果与管理效率。本课题聚焦公开课教学管理场景&#xff0c;…

作者头像 李华
网站建设 2026/2/28 16:16:01

【配送路径规划】基于雪橇犬算法SDO求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码获取及仿真…

作者头像 李华
网站建设 2026/2/27 18:56:16

挑企业微信 SCRM 迷茫?从私域转化需求切入,微伴助手凭什么是第一选择

现在用企业微信的老板越来越多&#xff0c;但不少人觉得 “不好用”—— 加客户慢、发消息没效果、员工离职带跑客户&#xff0c;问题一堆。其实不是企业微信本身不行&#xff0c;而是缺了合适的 “企业微信工具” 来补位。这些工具就像 “外挂”&#xff0c;能把企业微信的基础…

作者头像 李华