代码随想录算法训练营第六十六天 |101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿

news2024/11/24 14:36:49

101.孤岛的总面积

文字讲解:101. 孤岛的总面积 | 代码随想录

解题思路

本题要求找到不靠边的陆地面积,那么我们只要从周边找到陆地然后 通过 dfs或者bfs 将周边靠陆地且相邻的陆地都变成海洋,然后再去重新遍历地图 统计此时还剩下的陆地就可以了。

在遇到地图周边陆地的时候,将1都变为0,此时地图为这样:

 这里使用深搜

#include<bits/stdc++.h>
using namespace std;
int dir[4][2] = {0, 1, 1,0, 0,-1, -1,0};
int result =0 ;   //用于后续记录结果
void dfs(vector<vector<int>>& grid , int x, int y)
{
     grid[x][y] = 0;
     result++;
     int n = grid.size();
     int m = grid[0].size();
     for(int i=0 ; i<4 ; i++)
     {
         int nextx = x + dir[i][0];
         int nexty = y + dir[i][1];
         if(nextx<0 || nextx>= n || nexty < 0 ||nexty >= m) continue;  //越界了
         if(grid[nextx][nexty]==0) continue;   //已经是海了
         dfs(grid,nextx,nexty);
     }
     return;
}

int main()
{
    int n,m;
    cin >> n >> m;
    vector<vector<int>> grid(n,vector<int>(m,0));
    for(int i =0 ;i< n ; i++)
    {
        for(int j=0; j < m; j++)
        {
            cin>> grid[i][j];
        }
    }
    //将地图左侧和右侧的陆地变海洋
    for(int i = 0 ;i < n ; i++)
    {
        if(grid[i][0]==1) dfs(grid,i,0);
        if(grid[i][m-1]==1) dfs(grid,i,m-1);
    }
    for(int j=0 ; j< m ; j++)
    {
        if(grid[0][j]==1) dfs(grid,0,j);
        if(grid[n-1][j]==1) dfs(grid,n-1,j);
    }
    result = 0;   //全变为海洋后,再去遍历剩余的孤岛
    for(int i =0; i<n; i++)
    {
        for(int j =0 ;j < m; j++)
        {
            if(grid[i][j]==1) dfs(grid,i,j);
        }
    }
    cout << result << endl;
}

102.沉没孤岛

文字讲解:102. 沉没孤岛 | 代码随想录 

解题思路

步骤一:深搜或者广搜将地图周边的 1 (陆地)全部改成 2 (特殊标记)

步骤二:将水域中间 1 (陆地)全部改成 水域(0)

步骤三:将之前标记的 2 改为 1 (陆地)

这次我们使用广搜

#include<bits/stdc++.h>
using namespace std;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
void bfs(vector<vector<int>>& grid , int x, int y)
{
    queue<pair<int,int>> que;
    que.push({x,y});
    grid[x][y]=2;       //将连接的岛屿都变为2
    while(!que.empty())
    {
             pair<int,int> cur = que.front();
             que.pop();
             int curx = cur.first;
             int cury = cur.second;
        for(int i =0 ;i < 4; i++)
        {
             int nextx = curx + dir[i][0];
             int nexty = cury + dir[i][1];
             int n = grid.size();
             int m = grid[0].size();
             if(nextx<0 || nextx>= n || nexty <0 || nexty >=m ) continue;
             if(grid[nextx][nexty]==0 || grid[nextx][nexty]==2) continue;
             //如果下一个格子是海洋或者已经标记过的,就跳过
             que.push({nextx,nexty});
             grid[nextx][nexty] = 2;
        }
    }
}

int main()
{
    int n,m;
    cin >> n >> m;
    vector<vector<int>> grid(n,vector<int>(m,0));
    for(int i =0 ; i< n ; i++)
    {
        for(int j = 0 ; j< m ;j++)
        {
            cin>> grid[i][j];
        }
    }
    for(int i =0 ; i< n; i++)   //标记两侧
    {
        if(grid[i][0]==1) bfs(grid,i,0);
        if(grid[i][m-1]==1) bfs(grid,i,m-1);
    }
    for(int j =0 ; j< m; j++)   //标记上下
    {
        if(grid[0][j]==1) bfs(grid,0,j);
        if(grid[n-1][j]==1) bfs(grid,n-1,j);
    }
    for(int i =0 ; i< n ; i++)
    {
        for(int j = 0 ; j< m ;j++)
        {
            if(grid[i][j]==1) grid[i][j] = 0;   //变为海洋
            if(grid[i][j]==2 ) grid[i][j] = 1;
        }
    }
    for(int i =0 ; i< n ; i++)
    {
        for(int j = 0 ; j< m ;j++)
        {
            cout<< grid[i][j] << " ";
        }
        cout << endl;
    }
}

103.水流问题

文字讲解:103. 水流问题 | 代码随想录

思路一:遍历每个点,去看是否能到达两个边界,但这样肯定超时,遍历每个节点是m*n的复杂度,而深搜每个节点又是m*n的复杂度

思路二:逆流优化

从第一组边界上的节点 逆流而上,将遍历过的节点都标记上。

同样从第二组边界的边上节点 逆流而上,将遍历过的节点也标记上。

然后两方都标记过的节点就是既可以流太平洋也可以流大西洋的节点

 

 这里使用深搜

#include<bits/stdc++.h>
using namespace std;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
void dfs(vector<vector<int>>& grid ,vector<vector<bool>>& visited , int x, int y)
{   
        if(visited[x][y])
        return;
        visited[x][y] = true;
        for(int i = 0 ; i< 4 ;i++)
        {
            int nextx = x + dir[i][0];
            int nexty = y + dir[i][1];
            int n = grid.size();
            int m = grid[0].size();
            if(nextx<0 || nextx>= n || nexty<0 || nexty>=m) continue;  //越界
            if(grid[x][y] > grid[nextx][nexty]) continue;   //我们这里是从低到高遍历
            dfs(grid,visited,nextx,nexty);
        }
        return;
}

int main()
{
    int n,m;
    cin>>n>>m;
    vector<vector<int>> grid(n,vector<int>(m,0));
    vector<vector<bool>> firstBoard(n,vector<bool>(m,0));
    vector<vector<bool>> secondBoard(n,vector<bool>(m,0));
    for(int i =0 ;i< n; i++)
    {
        for(int j = 0; j<m ;j++)
        {
            cin>>grid[i][j];
        }
    }
    for(int i =0 ; i < n ;i++)
    {
        dfs(grid,firstBoard,i,0);
        dfs(grid,secondBoard,i,m-1);
    }
    for(int j=0 ; j<m ; j++)
    {
        dfs(grid,firstBoard,0,j);
        dfs(grid,secondBoard,n-1,j);
    }
    for(int i =0 ;i< n; i++)
    {
        for(int j = 0; j<m ;j++)
        {
            if(firstBoard[i][j]&&secondBoard[i][j]) cout<< i << " " << j <<endl;
        }
    }
}

104.建造最大岛屿

文字讲解: 104.建造最大岛屿 | 代码随想录

解题思路

思路一:计算地图的最大面积:遍历地图 + 深搜岛屿,时间复杂度为 n * n。 

每改变一个0的方格,都需要重新计算一个地图的最大面积,所以 整体时间复杂度为:n^4

 

思路二:

其实每次深搜遍历计算最大岛屿面积,我们都做了很多重复的工作。

只要用一次深搜把每个岛屿的面积记录下来就好。

第一步:一次遍历地图,得出各个岛屿的面积,并做编号记录。可以使用map记录,key为岛屿编号,value为岛屿面积

第二步:再遍历地图,遍历0的方格(因为要将0变成1),并统计该1(由0变成的1)周边岛屿面积,将其相邻面积相加在一起,遍历所有 0 之后,就可以得出 选一个0变成1 之后的最大面积。

拿如下地图的岛屿情况来举例: (1为陆地)

 

第二步:再遍历地图,遍历每一个0的位置,求最大面积即可 

 时间复杂度:O(n^2)

 

#include<bits/stdc++.h>
using namespace std;
int n,m;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
int area = 0; //面积
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y, int mark) {
    if (visited[x][y] || grid[x][y] == 0) return; // 终止条件:访问过的节点 或者 遇到海水
    visited[x][y] = true; // 标记访问过
    grid[x][y] = mark; // 给陆地标记新标签
    area++;
    for (int i = 0; i < 4; i++) {
        int nextx = x + dir[i][0];
        int nexty = y + dir[i][1];
        if (nextx < 0 || nextx >= n || nexty < 0 || nexty >= m) continue;  // 越界了,直接跳过
        dfs(grid, visited, nextx, nexty, mark);
    }
}

int main()
{
    cin >> n >> m;
    vector<vector<int>> grid(n,vector<int>(m,0));
    vector<vector<bool>> visited(n,vector<bool>(m,false));
    for(int i=0 ;i < n ; i++)
    {
        for(int j=0; j < m ; j++)
        {
            cin>>grid[i][j];
        }
    }
    int mask =2;   //从2开始标记
    unordered_map<int,int> map;   //用来存面积
    bool allGrid = true;
    for(int i=0 ;i < n ; i++)
    {
        for(int j=0; j < m ; j++)
        {
            if(grid[i][j] == 0) allGrid = false;
            if(!visited[i][j] && grid[i][j]==1)   //遇到辛岛屿了
            {
                area = 0;  //面积重置为0
                dfs(grid,visited,i,j,mask);
                map[ mask ] = area;   //记录这个岛屿的面积
                mask++;
            }
        }
    }
    if(allGrid)
    {
        cout << n * m <<endl;
        return 0;
    }
    
    int result = 0;
    unordered_set<int> visitedGrid;
    
    for(int i=0 ;i < n ; i++)
    {
        for(int j=0; j < m ; j++)
        {
            area = 1;   //变为1后的岛屿总面积
            visitedGrid.clear();   //每次换格子变1时需要重置
            if(grid[i][j]==0)
            {
                for (int k = 0; k < 4; k++) {
                    int neari = i + dir[k][1]; // 计算相邻坐标
                    int nearj = j + dir[k][0];
                    if (neari < 0 || neari >= n || nearj < 0 || nearj >= m) continue;
                    if (visitedGrid.count(grid[neari][nearj])) continue; // 添加过的岛屿不要重复添加
                    // 把相邻四面的岛屿数量加起来
                    area += map[grid[neari][nearj]];
                    visitedGrid.insert(grid[neari][nearj]); // 标记该岛屿已经添加过
                }
            }
            result = max(result,area);
        }
    }
    cout << result << endl;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

360°环绕拍摄图片的作用 欧保图 ORBITVU

360环绕拍摄图片在电商中的应用及其优势 ORBITVU 波兰 欧保图 360环绕拍摄图片是一种动态的产品展示方式&#xff0c;它允许消费者从不同角度全方位地查看产品&#xff0c;这种交互式的体验大大增强了用户的购物体验。以下是360环绕拍摄图片在电商中的一些具体应用及其带来的优…

FreeRTOS学习 -- 时间管理

在使用 FreeRTOS 的过程中通常会在一个任务函数中使用延时函数对这个任务延时&#xff0c;当执行延时函数的时候会进行任务切换&#xff0c;并且此任务就会进入阻塞态&#xff0c;直到延时完成&#xff0c;任务重新进入就绪态。 FreeRTOS 延时函数 1、函数 vTaskDelay() 在F…

Ubuntu下载QT5.8安装包-bestswinger课程

最近在看UP的QT开发课&#xff0c;真的找了巨久这个安装包&#xff0c;谁都不想在安装上花太多时间。。出一版小小教程吧&#xff5e; 首先打开qt download官网&#xff0c;5.8好像在镜像网站上没有看到&#xff0c;所以我最后还是老老实实官网了&#xff0c;而且5.8会小一点 …

90%网络工程师还是搞不清三层交换机是啥?

6月29日&#xff0c;HCIA新开班啦什么是三层交换机&#xff1f; 首先&#xff0c;我们先来解释一下三层交换机是什么。简单来说&#xff0c;它就是网络中的一个小老板&#xff0c;负责管理数据的流动。与普通的网络设备不同&#xff0c;三层交换机不仅能认识「MAC地址」&#…

小程序使用接口wx.getLocation配置

开通时需详细描述业务&#xff0c;否则可能审核不通过 可能需要绑定腾讯位置服务&#xff0c;新建应该&#xff0c;绑定到小程序 配置 权限声明&#xff1a;在使用wx.getLocation前&#xff0c;需要在app.json的permission字段中声明对用户位置信息的使用权限&#xff0c;并提…

可编程非线性RCD负载原理与应用

可编程非线性RCD负载&#xff08;Resistor-Capacitor-Diode&#xff09;是一种电子元件&#xff0c;其电阻、电容和二极管的特性可以通过编程进行控制和调整。这种负载广泛应用于电力系统、通信设备、电子设备等领域&#xff0c;具有很高的实用价值。 RCD负载的基本原理是利用电…

【CT】LeetCode手撕—160. 相交链表

目录 题目1- 思路2- 实现⭐160. 相交链表——题解思路 3- ACM 实现 题目 原题连接&#xff1a;160. 相交链表 1- 思路 模式识别&#xff1a;相交链表 ——> 判断是否相交 思路 保证 headA 是最长的那个链表&#xff0c;之后对其开始依次遍历 2- 实现 ⭐160. 相交链表—…

大厂晋升学习方法一:海绵学习法

早晨 30 分钟 首先&#xff0c;我们可以把起床的闹钟提前 30 分钟&#xff0c;比如原来 07:30 的闹钟可以改为 07:00。不用担心提前 30 分钟起床会影响休息质量&#xff0c;习惯以后&#xff0c;早起 30 分钟不但不会影响一天的精力&#xff0c;甚至可能反而让人更有精神。早起…

leetcode 二分查找·系统掌握 猜数字大小

题目&#xff1a; 题解&#xff1a; 使用最经典普通二分即可 int guessNumber(int n) {long l0,rn,mid;while(l<r){mid(rl)>>1;if(guess(mid)0)return mid;else if(guess(mid)-1)rmid-1;else lmid1;}return 0;}

kylin v10 离线安装chrome centos离线安装chrome linux离线安装谷歌浏览器

1. 先用自己联网的计算机&#xff0c;下载离线安装包&#xff0c;浏览器输入链接下载安装包&#xff1a; https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 1.2. 信创环境不用执行下面&#xff0c;因为没网 1.3. 若为阿里云服务器&#xff0c;或服…

基于自主发明专利的杰林码哈希算法、对称加密算法和无损压缩算法的可文件追踪管控且支持linux和windows的文件压缩包工具SDK和JLM PACK软件介绍

基于自主发明专利的杰林码哈希算法、对称加密算法和无损压缩算法的可文件追踪管控且支持linux和windows的文件压缩包工具SDK1.0版发布&#xff0c;下载链接为&#xff1a; JLM PACK SDK和软件的官方网站 注意测试授权证书yesine_jlmpack_test.license的有效期到2024年12月&am…

【AI副业指南】用AI做心理测试图文号,单月稳赚7000+(附详细教程)

大家好&#xff0c;我是画画的小强 因为AI的出现&#xff0c;很多自媒体副业项目变得简单容易上手&#xff0c;也给予很多想要在业余时间变现的朋友更丰富的项目选择。 今天分享的赛道绝对颠覆大家的认知&#xff0c;本期将叫大家如何通过AI在自媒体平台上做心理测试账号。 …

湖南(焦点小组)源点咨询 用户座谈会现场访谈之一点心得

湖南源点调研认为&#xff1a;访谈前&#xff0c;务必先明确最核心的目的。 一些初学的同学都知道&#xff0c;访谈首先要准备一个提纲&#xff0c;的确这是一个基础工作。但我在实际情况更常见到的是&#xff1a; 访谈提纲看似全面&#xff0c;各种维度都去问&#xff0c;但…

防晒服饰「进化论」:从标准到当代人的OOTD

【潮汐商业评论/原创】 “我&#xff0c;我老公&#xff0c;我儿子&#xff0c;身上80%都被‘防晒’承包了。我怕光老化&#xff0c;我老公怕热&#xff0c;我儿子容易晒脱皮。买蕉下&#xff0c;是因为看重它的标准&#xff0c;而且此‘防晒’已非彼‘防晒’了。”宝妈Timy正…

使用VisualBox+Vagrant搭建Centos虚拟机环境

1.下载并安装VisualBox&#xff1b; 2.下载并安装Vagrant; 3.打开cmd窗口&#xff0c;执行命令vagrant init centos/7&#xff0c;初始化centos环境&#xff0c;该步骤受网络带宽影响&#xff0c;可能挂级30分钟到1个小时&#xff1b; 4.启动虚拟机&#xff1a;vagrant up&…

如何使用LiveTargetsFinder生成实时活动主机URL列表

关于LiveTargetsFinder LiveTargetsFinder是一款功能强大的实时活动主机生成工具&#xff0c;该工具可以为广大研究人员以自动化的形式生成可供分析和测试的实时活动主机URL列表&#xff0c;并通过MassDNS、Masscan和Nmap自动过滤出无法访问的主机。 我们只需要提供一个域名作…

使用mysql的binlog进行数据恢复

1.mysql安装环境 在你本地电脑windows上建一个和生产环境一样的mysql版本 我的是 mysql5.7.43 安装教程可以自行上网搜&#xff08;这里不做介绍&#xff09; 可参考&#xff1a; 1.1安装路径 我的mysql安装路径&#xff1a; D:\mysql\mysql-5.7.43-winx64\bin * 1.2my.in…

小型超声波清洗机真的有用吗?深入测评四款优质精品,亮点多多

超声波洗眼镜机能够彻底清洁眼镜&#xff0c;去除顽固污渍和灰尘&#xff0c;其次是操作简便&#xff0c;对比传统的清洗方式用时短、效率高&#xff0c;避免了手动的麻烦&#xff0c;于是有很多眼镜使用者都选择了超声波清洗机。但由于目前超声波清洗机型号众多&#xff0c;如…

Erpnext安装

Erpnext安装 环境要求 Ubuntu 23.04 x86_64 Python 3.10.12 pip 23.0.1 node v18.16.0 npm 9.5.1 yarn 1.22.22 MariaDB 10.11.2 Redis 7.0.8 wkhtmltox 0.12.6.1 bench 5.22.6环境安装 Reids 安装 // 安装7.0.8 也可不指定版本 直接执行 sudo apt install redis-server s…

AI创作在论文写作中扮演什么角色?

近年来&#xff0c;随着科技的快速发展&#xff0c;AI已经逐渐渗透到了生活中的方方面面&#xff0c;其中也包含着学术领域。 作为学生党&#xff0c;你是否还在为期末论文&#xff0c;大学生实践报告而发愁&#xff1f; 有了这些AI写作神器&#xff0c;大学生们再也不用在期…