图论基础|695. 岛屿的最大面积、1020. 飞地的数量、130. 被围绕的区域

news/2024/6/18 21:24:22 标签: 图论

695. 岛屿的最大面积

力扣题目链接(opens new window)

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

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

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

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

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

思路:广度优先和深度优先皆可,遍历的时候计数,然后取最大数量即可

class Solution {
public:
    //深度优先版本
    int count=0;
    int result =0;
    int dir[4][2]={0,1,1,0,-1,0,0,-1};
    void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
        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;
            if(!visited[nextx][nexty] && grid[nextx][nexty] == 1){
                
                visited[nextx][nexty]=true;
                count++;
                dfs(grid,visited,nextx,nexty);

            }
        }
        
    }
    int maxAreaOfIsland(vector<vector<int>>& grid) {
       int n=grid.size(); int m=grid[0].size();
        vector<vector<bool>>visited=vector<vector<bool>>(n,vector<bool>(m,false));
        for(int i=0;i<n;i++){
            for(int j=0; j<m;j++){
                if(!visited[i][j]&&grid[i][j]==1){
                    count=1;//遇到陆地先计数
                    visited[i][j]=true;
                    dfs(grid,visited,i,j);
                    result=max(result,count);
                }
            }
        }
        return result;
    }
};
//广度优先版本
class Solution {
public:
 
    int count=0;
    int result =0;
    int dir[4][2]={0,1,1,0,-1,0,0,-1};
    void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
        queue<int>que;
        que.push(x);
        que.push(y);
        visited[x][y]=true;
        count++;
        while(!que.empty()){
            int xx=que.front(); que.pop();
            int yy=que.front(); que.pop();
            for(int i=0;i<4;i++){
                int nextx=  xx+dir[i][0];
                int nexty=  yy+dir[i][1];

                if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size())continue;
                if(!visited[nextx][nexty] && grid[nextx][nexty] == 1){
                
                    visited[nextx][nexty]=true;
                    count++;
                    que.push(nextx);
                    que.push(nexty);

                }
            }
        }
        
    }
    int maxAreaOfIsland(vector<vector<int>>& grid) {
       int n=grid.size(); int m=grid[0].size();
        vector<vector<bool>>visited=vector<vector<bool>>(n,vector<bool>(m,false));
        for(int i=0;i<n;i++){
            for(int j=0; j<m;j++){
                if(!visited[i][j]&&grid[i][j]==1){
                    count=0;
                    visited[i][j]=true;
                    dfs(grid,visited,i,j);
                    result=max(result,count);
                }
            }
        }
        return result;
    }
};

1020. 飞地的数量

力扣链接(opens new window)

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

一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。

返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

  • 输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
  • 输出:3
  • 解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。

  • 输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
  • 输出:0
  • 解释:所有 1 都在边界上或可以到达边界

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

遍历周边:分别遍历最左列(grid[i][0]),最右列(grid[i][m-1]),最上行(grid[0][j]),最下行(grid[n-1][j]),同时进行搜索,在搜索过程中将其置0。

class Solution {
public:
    //深度优先搜索
    int dir[4][2]={1,0,0,1,-1,0,0,-1};//四个方向
    int count;
    void dfs(vector<vector<int>>& grid, int x, int y){
        grid[x][y]=0;
        count++;
        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;
            if(grid[nextx][nexty]==1){
                // count++;
                // grid[nextx][nexty]=0;
                dfs(grid, nextx, nexty);
            }
        }
        return;
    }
    int numEnclaves(vector<vector<int>>& grid) {
        // int count=0;
        int n=grid.size();//行数
        int m=grid[0].size();//列数
        //遍历周边
        for(int i=0;i<n;i++){
            if(grid[i][0])dfs(grid, i,0);//遍历最左列
            if(grid[i][m-1])dfs(grid,i, m-1);//遍历最右列
        }
        for(int j=0; j<m;j++){
            if(grid[0][j])dfs(grid, 0, j);//遍历最上行
            if(grid[n-1][j])dfs(grid,n-1, j);//遍历最底行
        }
        
        //遍历整个网格,并计数
        count= 0;
        for(int i=0; i<n; i++){
            for(int j=0; j<m;j++){
                if(grid[i][j]){
                    // count++;
                    dfs(grid,i, j);
                }
            }
        }
        return count;
        

    }
};
//广度优先搜索
class Solution {
public:
    int count =0;
    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});
        count++;
        grid[x][y]=0;
        while(!que.empty()){
            pair<int,int>cur=que.front();que.pop();
            for(int i=0;i<4;i++){
                int nextx=cur.first+dir[i][0];
                int nexty=cur.second+dir[i][1];
                if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size())continue;
                if(grid[nextx][nexty]){
                    que.push({nextx,nexty});
                    count++;
                    grid[nextx][nexty]=0;
                }

            }
            
        }
        return;
    }
    int numEnclaves(vector<vector<int>>& grid) {
        int n=grid.size();//行数
        int m=grid[0].size();//列数
        //遍历周边并置0
        for(int i=0;i<n;i++){
            if(grid[i][0])bfs(grid,i,0);//遍历最左列
            if(grid[i][m-1])bfs(grid,i,m-1);//遍历最右列
        }
        for(int j=0;j<m;j++){
            if(grid[0][j]) bfs(grid,0,j);//遍历第一行
            if(grid[n-1][j]) bfs(grid,n-1,j);//遍历最后一行
        }
        //重新遍历整个网格并计算
        count=0;
        for(int i=0; i<n;i++) {
            for(int j=0;j<m;j++){
                if(grid[i][j]){
                    bfs(grid,i,j);
                }
            }
        }
        return count;
    }
};

130. 被围绕的区域

题目链接(opens new window)

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。

  • 输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
  • 输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
  • 解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的

思路:和上一题类似,只是需要把’飞地‘改为”X"

先广度优先或深度优先遍历周边,把周边的X换为'A',然后两个for循环遍历整个grid,遇到'A'换成’O',遇到'O'换成‘X'

//广度优先搜索
class Solution {
public:
    int dir[4][2]={0,1,1,0,0,-1,-1,0};
    void dfs(vector<vector<char>>& board, int x, int y){
        board[x][y]='A';
        for(int i=0;i<4;i++){
            int nextx=x+dir[i][0];
            int nexty=y+dir[i][1];
            if(nextx<0||nextx>=board.size()||nexty<0||nexty>=board[0].size())continue;
            if(board[nextx][nexty]=='O'){
                dfs(board,nextx,nexty);
            }
        }
        return;
    }
    void solve(vector<vector<char>>& board) {
        int n=board.size();//行数
        int m=board[0].size();//列数
        //遍历周边,把周边的'O'换成’A‘
        for(int i=0;i<n;i++){
            if(board[i][0]=='O')dfs(board,i,0);//遍历最左列
            if(board[i][m-1]=='O')dfs(board,i,m-1);//遍历最右列
        }

        for(int j=0;j<m;j++){
            if(board[0][j]=='O')dfs(board,0,j);//最上行
            if(board[n-1][j]=='O')dfs(board,n-1,j);//最下行
        }

        //遍历整个网格并替换
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(board[i][j]=='O')board[i][j]='X';
                if(board[i][j]=='A') board[i][j]='O';
                
            }
        }
        

    }
};
class Solution {
public:
    int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
    void bfs(vector<vector<char>>& board, int x, int y) {
        queue<pair<int, int>> que;
        que.push({x, y});
        board[x][y]='A';
        while (!que.empty()) {
            pair<int, int> cur = que.front();
            que.pop();
            for (int i = 0; i < 4; i++) {
                int nextx = cur.first + dir[i][0];
                int nexty = cur.second + dir[i][1];
                if (nextx < 0 || nextx >= board.size() || nexty < 0 ||
                    nexty >= board[0].size())
                    continue;
                if (board[nextx][nexty] == 'O') {
                    board[nextx][nexty] = 'A';
                    // cout<<"board[nextx][nexty]:"<<board[nextx][nexty]<<endl;
                    que.push({nextx, nexty});
                    
                }
            }
        }
    }
    void solve(vector<vector<char>>& board) {
        int n = board.size();
        int m = board[0].size();
        // 遍历周边
        for (int i = 0; i < n; i++) {
            if (board[i][0] == 'O')
                bfs(board, i, 0);
            if (board[i][m - 1] == 'O')
                bfs(board, i, m - 1);
        }
        for (int j = 0; j < m; j++) {
            if (board[0][j] == 'O')
                bfs(board, 0, j);
            if (board[n - 1][j] == 'O')
                bfs(board, n - 1, j);
        }

        // 遍历整个网格并替换
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                // cout<<"before: "<<board[i][j]<<endl;
                if (board[i][j] == 'O')
                    board[i][j] = 'X';
                if (board[i][j] == 'A')
                    board[i][j] = 'O';
                
                
            }
        }
    }
};

 参考:代码随想录


http://www.niftyadmin.cn/n/5448280.html

相关文章

扫雷(c++题解)

题目描述 题目描述 扫雷是一种计算机游戏&#xff0c;在 世纪 年代开始流行&#xff0c;并且仍然包含在某些版本的 Microsoft Windows 操作系统中。 在这个问题中&#xff0c;你正在一个矩形网格上玩扫雷游戏。 最初网格内的所有单元格都呈未打开状态。 其中 个不同的单…

网络层(IP层)

IP协议的本质&#xff1a;有将数据跨网络传输的能力 而用户需要的是将数据从主机A到主机B可靠地跨网络传输 IP的组成&#xff1a;目标网络目标主机 IP由目标网络和目标主机两部分组成&#xff0c;IP报文要进行传输&#xff0c;要先到达目标网络&#xff0c;然后经过路由器转到…

IPV6报文详解

目录 前言&#xff1a; IPV6报文格式 IPV6基本报头 IPV6扩展报头 前言&#xff1a; 首先IPV6是属于网络层的一种协议&#xff0c;作为下一代IP协议&#xff0c;而想要学习一种协议就必不可少的需要去具体的研究协议报文中的各个参数以及其对应的功能作用。 IPV6报文格式 I…

卷积篇 | YOLOv8改进之主干网络中引入可变形卷积DConv

前言:Hello大家好,我是小哥谈。可变形卷积模块是一种改进的卷积操作,它可以更好地适应物体的形状和尺寸,提高模型的鲁棒性。可变形卷积模块的实现方式是在标准卷积操作中增加一个偏移量offset,使卷积核能够在训练过程中扩展到更大的范围,从而实现对尺度、长宽比和旋转等各…

mineadmin前端安装启动

在上一篇文章中&#xff0c; 我们已经搭建好了后端环境并启动 mineadmin 快速安装部署&#xff08;docker环境&#xff09; 一、下载前端项目 1、在搭建后端时候&#xff0c;使用php bin/hyperf.php mine:install 的时候&#xff0c;有一个步骤是安装前端项目的。安装目录为&a…

【Python从入门到进阶】51、电影天堂网站多页面下载实战

接上篇《50、当当网Scrapy项目实战&#xff08;三&#xff09;》 上一篇我们讲解了使用Scrapy框架在当当网抓取多页书籍数据的效果&#xff0c;本篇我们来抓取电影天堂网站的数据&#xff0c;同样采用Scrapy框架多页面下载的模式来实现。 一、抓取需求 打开电影天堂网站&…

vue3+threejs新手从零开发卡牌游戏(九):添加抽卡逻辑和动效

首先优化下之前的代码&#xff0c;把game/deck/p1.vue中修改卡组方法和渲染卡组文字方法提到公共方法中&#xff0c;此时utils/common.ts完整代码如下&#xff1a; import { nextTick } from vue; import * as THREE from three; import * as TWEEN from tweenjs/tween.js impo…

机器学习 | 期望最大化(EM)算法介绍和实现

在现实世界的机器学习应用中&#xff0c;通常有许多相关的特征&#xff0c;但只有其中的一个子集是可观察的。当处理有时可观察而有时不可观察的变量时&#xff0c;确实可以利用该变量可见或可观察的实例&#xff0c;以便学习和预测不可观察的实例。这种方法通常被称为处理缺失…