首页 > 编程语言 >代码随想录算法训练营第 51 天 |LeetCode99岛屿数量 LeetCode100.岛屿的最大面积

代码随想录算法训练营第 51 天 |LeetCode99岛屿数量 LeetCode100.岛屿的最大面积

时间:2024-08-23 15:27:24浏览次数:11  
标签:LeetCode99 遍历 visit int 岛屿 随想录 vector graph

代码随想录算法训练营

Day51 代码随想录算法训练营第 51 天 |LeetCode99岛屿数量 LeetCode100.岛屿的最大面积


目录


前言

LeetCode200 岛屿数量

讲解文档

LCR 105. 岛屿的最大面积

讲解文档


一、广度优先搜索基础

1、用队列实现

2、代码框架:

(1)起始节点加入队列
(2)只要加入队列,立刻标记为访问过的节点
(3)开始遍历队列里的元素
1)从队列取元素
2)开始想当前节点的四个方向左右上下去遍历
3)坐标越界了,直接跳过
4)如果节点没被访问过
① 队列添加该节点为下一轮要遍历的节点
② 只要加入队列立刻标记,避免重复访问

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 表示四个方向
// grid 是地图,也就是一个二维数组
// visited标记访问过的节点,不要重复访问
// x,y 表示开始搜索节点的下标
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {
    queue<pair<int, int>> que; // 定义队列
    que.push({x, y}); // 起始节点加入队列
    visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点
    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]; // 获取周边四个方向的坐标
            if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 坐标越界了,直接跳过
            if (!visited[nextx][nexty]) { // 如果节点没被访问过
                que.push({nextx, nexty});  // 队列添加该节点为下一轮要遍历的节点
                visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问
            }
        }
    }

}

二、卡码网99岛屿数量(LeetCode200 岛屿数量 )

1.题目链接

卡码网99岛屿数量

2.思路

(1)深度优先搜索
1)思路:遍历所有点,遇到没有遍历过的陆地就是找到了新的岛屿,利用深度优先搜索将这个陆地点同一岛屿的所有陆地点都标记为已经搜索
2)深度优先搜索:
① 参数和返回值
参数:坐标,图数组,访问数组
② 终止条件:超出图边界,已经访问过,海洋
没有终止条件的写法:将终止条件写在递归调用前,不满足条件的不调用
③ 操作:
遍历上下左右,递归调用

(2)广度优先搜索
1)思路:遍历所有点,遇到没有遍历过的陆地就是找到了新的岛屿,利用广度优先搜索将这个陆地点同一岛屿的所有陆地点都标记为已经搜索
2)广度优先搜索:
① 参数和返回值
参数:坐标,图数组,访问数组
② 队列:
每次进行bfs先创建队列,把当前点放进去,标记visit

③ 遍历:
队列不空就不停止
每次遍历先求当前点坐标,将当前点弹出去
④ 操作:

  • 遍历上下左右
  • 每次检验点是否在范围内,且是没有visit过的陆地
  • 点入队,visit标记

注意:每次点入队的时候进行visit标记

3.题解

(1)深度优先搜索

#include<bits/stdc++.h>
using namespace std;
int res=0;
int direction[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void dfs(int x,int y,vector<vector<int>>&graph,vector<vector<int>>&visit)
{
    if(x<=0 || y<=0||x>graph.size()||y>graph[0].size())return;
    if(graph[x][y]==0||visit[x][y]==1)return;
    visit[x][y]=1;
    for(int i=0;i<4;i++)
    {
        int newx=x+direction[i][0];
        int newy=y+direction[i][1];
        if(newx<=0 || newy<=0||newx>graph.size()||newy>graph[0].size())continue;
        dfs(newx,newy,graph,visit);
    }
}
int main()
{
    int n;
    int m;
    cin>>n>>m;
    vector<vector<int>>graph(n+5,vector<int>(m+5,0));
     vector<vector<int>>visit(n+5,vector<int>(m+5,0));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>graph[i][j];
        }
    }
    int res=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(graph[i][j]==1&&visit[i][j]==0)
            {
                res++;// 遇到没访问过的陆地--新的岛屿
                //用深度优先搜索,将当前陆地相连的所有陆地记作visit=1
                dfs(i,j,graph,visit);
            }
        }
    }
    cout<<res;
    return 0;
    
}

(2)广度优先搜索

#include<bits/stdc++.h>
using namespace std;
int direction[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void bfs(int x,int y,int n,int m,vector<vector<int>>&graph,vector<vector<int>>&visit)
{
    queue<pair<int,int>>q;
    q.push({x,y});
    visit[x][y]=1;
    while(!q.empty())
     {
        int curx=q.front().first ;
        int cury=q.front().second;
        q.pop();
        for(int i=0;i<4;i++)
        {
            int newx=curx+direction[i][0];
            int newy=cury+direction[i][1];
            if(newx<=0 || newy<=0||newx>n||newy>m)
            {
                continue;
            }
            if(graph[newx][newy]==1 && visit[newx][newy]==0){
                q.push({newx,newy});
                visit[newx][newy]=1;
            }
        }
     }  
}
int main()
{
    int n;
    int m;
    cin>>n>>m;
    vector<vector<int>>graph(n+5,vector<int>(m+5,0));
     vector<vector<int>>visit(n+5,vector<int>(m+5,0));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>graph[i][j];
        }
    }
    int res=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(graph[i][j]==1&&visit[i][j]==0)
            {
                res++;// 遇到没访问过的陆地--新的岛屿
                //用深度优先搜索,将当前陆地相连的所有陆地记作visit=1
                bfs(i,j,n,m,graph,visit);
            }
        }
    }
    cout<<res;
    return 0;
}

三、LCR 105. 岛屿的最大面积

1.题目链接

卡码网100.岛屿的最大面积

2.思路

总体思路:遍历所有点,遇到没有遍历过的陆地就是找到了新的岛屿,利用深度优先搜索将这个陆地点同一岛屿的所有陆地点都标记为已经搜索,求岛屿的面积
(1)方法1:dfs处理当前点的上下左右的visit
1) 遍历点
如果点是陆地并且没有visit,那么:
① 岛屿面积重置为1(当前点在此处进行处理)
② 当前点标记visit
③ 深度优先搜索
④ res=max(res,s)
2)深度优先搜索
①参数和返回值
参数:坐标,图数组,访问数组
② 终止条件:将终止条件写在递归调用前,不满足条件的不调用,也不进行visit和面积处理
③ 操作:
遍历上下左右
跳过超出图范围的
是陆地并且没有visit的点:

  • 标记visit,岛屿面积+1
  • 递归调用

(2)方法1:dfs处理当前点的上下左右的visit
1) 遍历点
如果点是陆地并且没有visit,那么:
① 岛屿面积重置为0(当前点在dfs进行处理)
② 深度优先搜索
③ res=max(res,s)
2)深度优先搜索
①参数和返回值
参数:坐标,图数组,访问数组
② 终止条件:如果点是visit过的,或者是海洋,跳过
③ 操作:
当前点标记visit,岛屿面积+1
遍历上下左右
跳过超出图范围的
递归调用

3.题解

方法一:每次处理与当前点直接相连的点的visit和面积

#include<bits/stdc++.h>
using namespace std;
int s;
int direction[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void dfs(int x,int y,vector<vector<int>>&graph,vector<vector<bool>>&visit)
{
    for(int i=0;i<4;i++)
    {
        int nextx=x+direction[i][0];
        int nexty=y+direction[i][1];
        if(nexty<0||nextx<0||nexty>=graph[0].size()||nextx>=graph.size())
        {
            continue;
        }
        if(graph[nextx][nexty]==1 && visit[nextx][nexty]==0)
        {
            visit[nextx][nexty]=1;
            s++;
            dfs(nextx,nexty,graph,visit);
        }
    }
}
int main()
{
    int n;
    int m;
    int res=0;
    cin>>n>>m;
    vector<vector<int>>graph(n,vector<int>(m,0));
    vector<vector<bool>>visit(n,vector<bool>(m,false));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            cin>>graph[i][j];
        }
    }
     for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(graph[i][j]==1&&visit[i][j]==false)//提前检验,起到剪枝作用
            {
                s=1;//当前点算一个(重置面积)
                visit[i][j]=1;
                dfs(i,j,graph,visit);
                res=max(res,s);
            }
        }
    }
    cout<<res;
    return 0;
}

方法2:每次处理当前点的visit和面积

#include<iostream>
#include<vector>
using namespace std;
int s;
int direction[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void dfs(int x,int y,vector<vector<int>>&graph,vector<vector<int>>&visit)
{
    if(graph[x][y]==0||visit[x][y]==1)return;
    visit[x][y]=1;
    s++;
    for(int i=0;i<4;i++)
    {
        int nextx=x+direction[i][0];
        int nexty=y+direction[i][1];
        if(nexty<0||nextx<0||nexty>=graph[0].size()||nextx>=graph.size())
        {
            continue;
        }
        dfs(nextx,nexty,graph,visit);
    }
}
int main()
{
    int n;
    int m;
    int res=0;
    cin>>n>>m;
    vector<vector<int>>graph(n,vector<int>(m,0));
    vector<vector<int>>visit(n,vector<int>(m,0));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            cin>>graph[i][j];
        }
    }
     for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(graph[i][j]==1&&visit[i][j]==0)//提前检验,起到剪枝作用
            {
                s=0;//当前点算一个(重置面积)
                
                dfs(i,j,graph,visit);
                res=max(res,s);
            }
    
            
        }
    }
    cout<<res;
    return 0;
}

标签:LeetCode99,遍历,visit,int,岛屿,随想录,vector,graph
From: https://blog.csdn.net/2301_79647020/article/details/141460054

相关文章

  • 代码随想录算法训练营第 49 天 |LeetCode42 接雨水 LeetCode84 柱状图中最大面积矩形
    代码随想录算法训练营Day49代码随想录算法训练营第49天|LeetCode42接雨水LeetCode84柱状图中最大面积矩形目录代码随想录算法训练营前言LeetCode42接雨水LeetCode84柱状图中最大面积矩形一、LeetCode42接雨水1.题目链接2.思路3.题解二、LeetCode84柱状......
  • 代码随想录算法训练营第 48 天 |LeetCode 739. 每日温度 LeetCode496.下一个更大元素
    代码随想录算法训练营Day48代码随想录算法训练营第48天|LeetCode739.每日温度LeetCode496.下一个更大元素ILeetCode503.下一个更大元素II目录代码随想录算法训练营前言LeetCode739.每日温度LeetCode496.下一个更大元素ILeetCode503.下一个更大元素II一......
  • 代码随想录day 38 || 322 零钱兑换,279 完全平方数,139 单词拆分
    322零钱找还funccoinChange(coins[]int,amountint)int{ //装满,并且硬币无限,可以类比完全背包问题 //dp[i][j]表示前i个物品装满容量为j的背包所需要的最少物品数量 //递推公式dp[i][j]=min(dp[i-1][j],dp[i][j-w(i)]+1)//不装物品i的物品数量,装物品i的物品数......
  • 代码随想录DAY22 - 回溯算法 - 08/21
    目录理论回顾什么是回溯法回溯法的效率回溯法解决的问题如何理解回溯组合题干思路和代码递归法递归优化:剪枝组合总和Ⅲ题干思路和代码递归法递归优化电话号码的字母组合题干思路和代码递归法理论回顾什么是回溯法回溯是一种类似枚举的搜索方法,回溯和......
  • 代码随想录DAY23 - 回溯算法 - 08/22
    组合总和题干题目:给你一个无重复元素的整数数组candidates和一个目标整数target,找出candidates中可以使数字和为目标数target的所有不同组合,并以列表形式返回。你可以按任意顺序返回这些组合。candidates中的同一个数字可以无限制重复被选取。如果至少......
  • 代码随想录算法训练营第二十三天(回溯 二)
    力扣题部分:39.组合总和题目链接:.-力扣(LeetCode)题面:给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。candid......
  • 代码随想录算法训练营第二十二天(回溯 一)
    开始学习回溯!回溯理论基础代码随想录文章链接:代码随想录文章摘要:什么是回溯法回溯法也可以叫做回溯搜索法,它是一种搜索的方式。在二叉树系列中,我们已经不止一次,提到了回溯。回溯是递归的副产品,只要有递归就会有回溯。所以以下讲解中,回溯函数也就是递归函数,指的都是一......
  • 代码随想录Day23
    131.分割回文串给你一个字符串s,请你将s分割成一些子串,使每个子串都是回文串。返回s所有可能的分割方案。示例1:输入:s="aab"输出:[["a","a","b"],["aa","b"]]示例2:输入:s="a"输出:[["a"]]提示:1<=s.length<=16s仅由......
  • 「代码随想录算法训练营」第四十四天 | 图论 part2
    200.岛屿数量题目链接:https://leetcode.cn/problems/number-of-islands/description/文章讲解:https://programmercarl.com/kamacoder/0099.岛屿的数量深搜.html题目难度:中等题目状态:看题解思路一:深搜版方法dfs:参数:接受一个字符网格grid和当前坐标(r,c)。功能:......
  • 给自己复盘的随想录笔记-移除元素
    双指针法双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。定义快慢指针快指针:寻找新数组的元素,新数组就是不含有目标元素的数组慢指针:指向更新新数组下标的位置相关题目删除有序数组中的重复项解题思路:解法:双指针首先注意数组......