岛屿类问题

问题基础

如何在二维矩阵中使用 DFS 搜索呢?如果你把二维矩阵中的每一个位置看做一个节点,这个节点的上下左右四个位置就是相邻节点,那么整个矩阵就可以抽象成一幅网状的「图」结构。

根据二叉树的遍历框架改写出二维矩阵的 DFS 代码框架:

// 二叉树遍历框架
void traverse(TreeNode root) {traverse(root.left);traverse(root.right);
}// 二维矩阵遍历框架
void dfs(int[][] grid, int i, int j, boolean[][] visited) {int m = grid.length, n = grid[0].length;if (i < 0 || j < 0 || i >= m || j >= n) {// 超出索引边界return;}if (visited[i][j]) {// 已遍历过 (i, j)return;}// 进入节点 (i, j)visited[i][j] = true;dfs(grid, i - 1, j, visited); // 上dfs(grid, i + 1, j, visited); // 下dfs(grid, i, j - 1, visited); // 左dfs(grid, i, j + 1, visited); // 右visited[i][j] = false;
}

DFS

200. 岛屿数量

class Solution {public:int numIslands(vector<vector<char>>& grid) {int m = grid.size();int n = grid[0].size();int ans = 0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]=='1'){dfs(grid,i,j);ans++;}}}return ans;}void dfs(vector<vector<char>>&grid, int i,int j){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n){return;}if(grid[i][j]=='0')return;grid[i][j]='0';dfs(grid,i+1,j);dfs(grid,i-1,j);dfs(grid,i,j+1);dfs(grid,i,j-1);return;}
};

694. 不同的岛屿数量

class Soultion694
{public:Soultion694() {}
public:int numDistinctIslands(vector<vector<int>>& grid){int m = grid.size();int n = grid[0].size();unordered_map<string,int> hashmap;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1){string res;dfs(grid,i,j,res,666);hashmap[res]++;}}}return hashmap.size();}void dfs(vector<vector<int>>& grid, int i, int j, string& str, int dir){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n){return;}if(grid[i][j]==0){return;}grid[i][j]=0;str += std::to_string(dir)+",";dfs(grid,i-1,j,str,1);dfs(grid,i+1,j,str,2);dfs(grid,i,j-1,str,3);dfs(grid,i,j+1,str,4);str += std::to_string(-dir)+",";return;}
};

695. 岛屿的最大面积

class Solution {public:int maxAreaOfIsland(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();int ans = 0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1){int area = 0;dfs(grid,i,j,area);ans = max(ans,area);}}}return ans;}void dfs(vector<vector<int>>& grid, int i,int j,int& area){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n)return;if(grid[i][j]==0)return;area++;grid[i][j]=0;dfs(grid,i-1,j,area);dfs(grid,i+1,j,area);dfs(grid,i,j-1,area);dfs(grid,i,j+1,area);return;}
};

711. Number of Distinct Islands II

class Solution711
{public:Solution711() {}int numDistinctIslands2(vector<vector<int>>& grid){int m = grid.size();int n = grid[0].size();set<vector<pair<int,int>>> distinct;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1){vector<pair<int,int>> pattern;dfs(grid,pattern,i,j,i,j);distinct.insert(normalize(pattern));}}}return distinct.size();}void dfs(vector<vector<int>>&grid, vector<pair<int,int>>& pattern, int i0, int j0, int i, int j){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n){return;}if(grid[i][j]<=0){return;}grid[i][j]=-1;pattern.emplace_back(i-i0,j-j0);static constexpr int dx[4] = {-1,1,0,0};static constexpr int dy[4] = {0,0,-1,1};for(int k=0;k<4;k++){dfs(grid,pattern ,i0,j0,i+dx[k],j+dy[k]);}return;}vector<pair<int,int>> normalize(vector<pair<int,int>> pattern){vector<vector<pair<int,int>>> ret(8,vector<pair<int,int>>());for(auto cur:pattern){int x = cur.first, y = cur.second;ret[0].emplace_back(x,y);ret[1].emplace_back(-x,y);ret[2].emplace_back(x,-y);ret[3].emplace_back(-x,-y);ret[4].emplace_back(y,x);ret[5].emplace_back(y,-x);ret[6].emplace_back(-y,x);ret[7].emplace_back(-y,-x);}for(int i = 0;i < 8; i++){sort(ret[i].begin(),ret[i].end());  // 对八种形状按照从上到下和从左到右进行排序 1的位置int r_offset = 0 - ret[i][0].first; // 将每种形状的最上边 最左边的1的位置记录为(0,0)int l_offset = 0 - ret[i][0].second; // 统一规规范化 最其中最小的for(int j=0;j<ret[i].size();j++){ret[i][j].first += r_offset;ret[i][j].second += l_offset;}}sort(ret.begin(),ret.end());return ret[0];}};

1020. 飞地的数量

class Solution {public:int numEnclaves(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();for(int i=0;i<m;i++){if(grid[i][0]==1){dfs(grid,i,0);}if(grid[i][n-1]==1){dfs(grid,i,n-1);}}for(int i=0;i<n;i++){if(grid[0][i]==1){dfs(grid,0,i);}if(grid[m-1][i]==1){dfs(grid,m-1,i);}}int count{0};for(int i=1;i<m;i++){for(int j=1;j<n;j++){if(grid[i][j]==1){count++;}}}return count;}void dfs(vector<vector<int>>&grid,int i,int j){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n)return;if(grid[i][j]==0)return;grid[i][j]=0;dfs(grid,i-1,j);dfs(grid,i+1,j);dfs(grid,i,j-1);dfs(grid,i,j+1);}
};

1254. 统计封闭岛屿的数目

class Solution {public:int closedIsland(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();for(int i=0;i<m;i++){if(grid[i][0]==0){dfs(grid,i,0);}if(grid[i][n-1]==0){dfs(grid,i,n-1);}}for(int i=0;i<n;i++){if(grid[0][i]==0){dfs(grid,0,i);}if(grid[m-1][i]==0){dfs(grid,m-1,i);}}int count{0};for(int i=1;i<m;i++){for(int j=1;j<n;j++){if(grid[i][j]==0){dfs(grid,i,j);count++;}}}return count;}void dfs(vector<vector<int>>&grid, int i,int j){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n)return;if(grid[i][j]==1)return;grid[i][j]=1;dfs(grid,i-1,j);dfs(grid,i+1,j);dfs(grid,i,j-1);dfs(grid,i,j+1);return;}
};

1905. 统计子岛屿

class Solution {public:int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {int m = grid1.size();int n = grid1[0].size();for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid1[i][j]==0&&grid2[i][j]==1){dfs(grid2,i,j);}}}int count{0};for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid2[i][j]==1){dfs(grid2,i,j);count++;}}}return count;}void dfs(vector<vector<int>>& grid2,int i,int j){int m = grid2.size();int n = grid2[0].size();if(i<0||i>=m||j<0||j>=n)return;if(grid2[i][j]==0)return;grid2[i][j]=0;dfs(grid2,i-1,j);dfs(grid2,i+1,j);dfs(grid2,i,j-1);dfs(grid2,i,j+1);return;}
};

463. 岛屿的周长

这道题目主要需要清楚,1格子的每条边被算作周长当且仅当这条边为网格边界或者相邻的另一个格子为水域。因此,可以遍历每个陆地格子,对其四个方向是否为边界或者水域,通过遍历就可以得到。

class Solution {public:int islandPerimeter(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();int ans = 0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1){dfs(grid,i,j,ans);}}}return ans;}void dfs(vector<vector<int>>&grid, int i,int j,int& ans){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n){ans++;return;}if(grid[i][j]==0){ans++;return;}if(grid[i][j]==2)return;grid[i][j]=2;dfs(grid,i-1,j,ans);dfs(grid,i+1,j,ans);dfs(grid,i,j-1,ans);dfs(grid,i,j+1,ans);return;}
};

剑指 Offer II 105. 岛屿的最大面积

class Solution {public:int maxAreaOfIsland(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();int ans = 0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1){int area{0};dfs(grid,i,j,area);ans = max(area, ans);}}}return ans;}void dfs(vector<vector<int>>& grid, int i,int j,int& area){int m = grid.size();int n = grid[0].size();if(i<0||i>=m||j<0||j>=n){return;}if(grid[i][j]==0)return;grid[i][j]=0;area++;dfs(grid,i-1,j,area);dfs(grid,i+1,j,area);dfs(grid,i,j-1,area);dfs(grid,i,j+1,area);return;}
};

130. 被围绕的区域

class Solution {public:void solve(vector<vector<char>>& board) {int m = board.size();int n = board[0].size();for(int i=0;i<m;i++){if(board[i][0]=='O')dfs(board,i,0,'#');if(board[i][n-1]=='O')dfs(board,i,n-1,'#');}for(int i=0;i<n;i++){if(board[0][i]=='O')dfs(board,0,i,'#');if(board[m-1][i]=='O')dfs(board,m-1,i,'#');}// for(int i=0;i<m;i++){//     for(int j=0;j<n;j++){//         if(board[i][j]=='O'){//             dfs(board,i,j,'X');//         }//     }// }// for(int i=0;i<m;i++){//     for(int j=0;j<n;j++){//         if(board[i][j]=='#'){//             dfs(board,i,j,'O');//         }//     }// }for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(board[i][j]=='#'){board[i][j]='O';}else if (board[i][j]=='O') {board[i][j]='X';}}}}void dfs(vector<vector<char>>&board, int i,int j, char ch){int m = board.size();int n = board[0].size();if(i<0||i>=m||j<0||j>=n)return;if(board[i][j]==ch || board[i][j]=='X')return;board[i][j]=ch;dfs(board,i-1,j,ch);dfs(board,i+1,j,ch);dfs(board,i,j-1,ch);dfs(board,i,j+1,ch);return;}
};

827. 最大人工岛

class Solution {public:inline bool inArea(const vector<vector<int>>& grid,int i,int j){return i>=0 && i<grid.size() && j>=0 && j<grid[0].size();}int dfs(vector<vector<int>>& grid, int i, int j, int index){if(!inArea(grid,i,j))return 0;if(grid[i][j]!=1)return 0;grid[i][j]=index;return (1+dfs(grid,i-1,j,index)+dfs(grid,i+1,j,index)+dfs(grid,i,j-1,index)+dfs(grid,i,j+1,index));}set<int> findNeighbour(const vector<vector<int>>& grid, int i, int j){set<int> hashset;if(inArea(grid,i-1,j)&&grid[i-1][j]!=0)hashset.insert(grid[i-1][j]);if(inArea(grid,i+1,j)&&grid[i+1][j]!=0)hashset.insert(grid[i+1][j]);if(inArea(grid,i,j-1)&&grid[i][j-1]!=0)hashset.insert(grid[i][j-1]);if(inArea(grid,i,j+1)&&grid[i][j+1]!=0)hashset.insert(grid[i][j+1]);return hashset;}int largestIsland(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();int index = 2;int maxArea = 0;if(m==0)return 1;unordered_map<int,int> hashmap;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==1){int area = 0;area = dfs(grid,i,j,index);hashmap[index] = area;index++;maxArea = max(maxArea, area);}}}if(maxArea==0)return 1;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j]==0){set<int> hashset = findNeighbour(grid,i,j);if(hashset.empty())continue;int area = 1;for(auto it=hashset.begin();it!=hashset.end();it++){area += hashmap[*it];}maxArea = max(maxArea, area);}}}return maxArea;}
};

UF

305. 岛屿数量 II

class Solution305
{public:class UF{public:int amounts;vector<int> parent;vector<int> size;public:UF() {}UF(int n){amounts = n;parent.resize(n);size.resize(n);for(int i=0;i<n;i++){parent[i]=i;size[i]=1;}}int find(int index){while (parent[index]!=index) {parent[index] = parent[parent[index]];index = parent[index];}return parent[index];}bool isconnected(int p,int q){int rootP = find(p);int rootQ = find(q);return rootP==rootQ;}int count(){return amounts;}void uion(int p,int q){int rootP = find(p);int rootQ = find(q);if(rootP==rootQ)return;if(size[rootP]>size[rootQ]){parent[rootQ] = rootP;size[rootP] += size[rootQ];}else {parent[rootP] = rootQ;size[rootQ] += size[rootP];}amounts--;return;}};
public:Solution305() {}vector<int> numIslands2(int m, int n,const vector<vector<int>>& positions){vector<int> parents(m*n,-1);vector<vector<int>> grid(m,vector<int>(n,0));vector<int> ans(positions.size(),0);static constexpr int dx[4] = {0,0,-1,1};static constexpr int dy[4] = {-1,1,0,0};int count = 0;for(int i=0;i<positions.size();i++){int cx = positions[i][0], cy = positions[i][1];int id = cx*n+cy;if(parents[id]!=-1){        // 重复添加ans[i] = count;continue;}grid[cx][cy]=1;     // 新添加parents[id]=id;count++;for(int k = 0;k<4;k++){int nx = cx + dx[k];int ny = cy + dy[k];int nxt_id = nx * n + ny;if(nx<0||nx>=m||ny<0||ny>=n||grid[nx][ny]==0||parents[nxt_id]==-1) // 单独的岛屿的父节点是自己continue;else {int rootid = findRoot(parents,id);int rootnxt_id = findRoot(parents,nxt_id);if(rootid!=rootnxt_id){             // 发现相邻岛屿 且和自身的父节点不同 可以进行合并  那么就不是新岛屿parents[rootid]==rootnxt_id;count--;}}}ans[i] = count;}return ans;}int findRoot(vector<int>& parents, int index){while (parents[index]!=index) {parents[index] = parents[parents[index]];index = parents[index];}return index;}
};

leetcode岛屿类问题相关推荐

  1. 岛屿类问题通用解法与DFS框架

    参考链接: https://leetcode.cn/problems/number-of-islands/solution/dao-yu-lei-wen-ti-de-tong-yong-jie-fa- ...

  2. 岛屿类-网格类问题-DFS | 力扣695. 岛屿的最大面积

    思路参考上文: 岛屿类-网格类问题-DFS | 力扣200. 岛屿数量 本文讲解695. 岛屿的最大面积问题,属于常见的岛屿类-网格类问题 本题使用DFS的思想 题目 给定一个包含了一些 0 和 1 ...

  3. 岛屿类-网格类问题-DFS | 力扣200. 岛屿数量

    本文讲解200. 岛屿数量问题,属于常见的岛屿类-网格类问题 本题使用DFS的思想 1 题目 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围, ...

  4. 岛屿类问题DFS遍历框架

    dfs在grid结构中进行,遍历起来比二叉树的遍历更加冗长复杂 相关问题 看leetcode岛屿问题 463 695 827 200等. //grid DFS遍历框架void dfs(int[][] ...

  5. 【leetcode】岛屿类问题的通用解法

    在 LeetCode 中,「岛屿问题」是一个系列系列问题,比如 200. 岛屿数量 (Easy) 463. 岛屿的周长 (Easy) 695. 岛屿的最大面积 (Medium) 827. 最大人工岛 ...

  6. 岛屿类问题的广度优先深度优先双解法(Leetcode题解-Python语言)

    695. 岛屿的最大面积 先上最经典的题目,详细思路看这题的官方题解,简单来说的岛屿问题就是遍历二维数组,一般都是从一块陆地开始,进行深度优先或者广度优先搜索,每次上下左右四个方向选其一然后寻找下一块 ...

  7. Leetcode岛屿问题系列分析

    在 LeetCode 中,「岛屿问题」是一个系列系列问题,比如: 200. 岛屿数量 (Medium) 463. 岛屿的周长 (Easy) 695. 岛屿的最大面积 (Medium) 827. 最大人 ...

  8. LeetCode岛屿的最大面积

    剑指 Offer II 105. 岛屿的最大面积 给定一个由 0 和 1 组成的非空二维数组 grid ,用来表示海洋岛屿地图. 一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻 ...

  9. LeetCode 岛屿数量

    给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成. 此外,你可以假设该网格的四条边 ...

最新文章

  1. 10 个有用的 PHP 代码
  2. python设置字符间距_python字符串处理以及字符串格式化
  3. Spring 知识点详解
  4. 西安工业大学计算机专业好吗,西安工业大学(专业学位)计算机技术考研难吗
  5. python resample函数_18_python_pandas_DataFrame使用指南(上)(1-4)
  6. 代码规范以及单元测试项目
  7. 使用minikube在windows构建kubernetes群集
  8. matlab 读取同一文件中所有图像_matlab 批量读取文件夹内所有图片的几种方法
  9. 13个Python小游戏(含源码),开始敲起来,玩吧!
  10. 窃取百度搜索结果曝光,今日头条一直穿着“皇帝的新装”?
  11. 算法图解-狄克斯特拉算法
  12. Android 如何让你的App分享给别人
  13. gitee教程(超全,超详细,超长)
  14. 用canvas实现一个简易绘图工具
  15. python unicode码转换_python实现unicode转中文及转换默认编码的方法
  16. 利用公式计算π=4(1-1/3+1/5-1/7+1/9-...)的近似值,直到括号中最后一项的绝对值小于0.000001为止
  17. 阿里面经总结:阿里三面+交叉面+hr面试
  18. 【CVPR 2021】解决目标检测长尾分布:Adaptive Class Suppression Loss for Long-Tail Object Detection
  19. photoshop是中文版怎么改成英文版!!
  20. 提醒大家有关越狱组it学院vip会员有猫腻,要小心。。。

热门文章

  1. python学习之路0x00
  2. vue-cli 原理分析
  3. 大数据之Linux 基础
  4. C#中用RSA算法生成公钥和私钥
  5. Java基础 项目实例五 简易聊天系统
  6. 关于.Net与J2EE的比较,到底用微软平台还是Java平台的问题
  7. C语言>>百钱百鸡问题。鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买百鸡,翁、母、雏各几何 ?
  8. linux系统中shell脚本最全详解二shell条件判断语法介绍函数分析
  9. 利用spring+springMvc对单点登录(SSO)的简单实现(含源码)
  10. 台大郭彦甫教授Matlab讲解笔记(一)