LC 1254:统计封闭岛屿的数目(DFS)

统计封闭岛屿的数目


问题描述:
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。

我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。

如果一座岛屿完全由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。

请返回封闭岛屿的数目。

示例1:

输入:grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
输出:2
解释:
灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。

示例2:

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

解题思路:

  首先我们需要遍历整个岛屿,如果当前位置为0(陆地),我们就需要判断该位置所在的岛屿是否为封闭岛屿。dfs上下左右四个方向,如果四个方向全部都是陆地,则返回真,总数+1。(注意:dfs的时候需要把碰到陆地标记为水域,这样就可以避免下一次遍历的时候重复计算了)
  此题不需要回溯,因为是求同一区域,不需要计算路径。

图解:

第一次从左上角开始进入dfs

(1)变为1,并从四个方向dfs

(2)第一次返回0,并把陆地0都变成了水域1.

(3)当进入四周都是水域的陆地时,返回1

代码如下:

#include<iostream>
#include<vector>
using namespace std;
	int dfs(int i,int j,vector<vector<int> >& grid){
		if(i<0||j<0||i>=grid.size()||j>=grid[i].size()){//不满足条件 
			return 0;
		}
		if(grid[i][j]==1){//如果碰到水域返回1 
			return 1;
		}
		grid[i][j]=1;//如果碰到陆地则标记为水域 
		int x1= dfs(i+1,j,grid);
		int x2= dfs(i-1,j,grid);
		int y1= dfs(i,j+1,grid);
		int y2= dfs(i,j-1,grid);
		//四个方向全为水域返回1 
		if(x1&&x2&&y1&&y2){
			return 1;
		}
		return 0;
	}
	int closedIsland(vector<vector<int> >& grid) {
		int sum=0;
		for(int i=1;i<grid.size()-1;i++){//边缘部分肯定不是岛屿,所以从1开始 
			for(int j=1;j<grid[i].size()-1;j++){
				if(grid[i][j]==0){ //如果是陆地 
					if(dfs(i,j,grid)){
						sum++;
						}
					}
				}
		} 
			return sum;
    }
    
int main(){
	vector<vector<int> > grid={{0,0,1,1,0,1,0,0,1,0},{1,1,0,1,1,0,1,1,1,0},{1,0,1,1,1,0,0,1,1,0},{0,1,1,0,0,0,0,1,0,1},{0,0,0,0,0,0,1,1,1,0},{0,1,0,1,0,1,0,1,1,1},{1,0,1,0,1,1,0,0,0,1},{1,1,1,1,1,1,0,0,0,0},{1,1,1,0,0,1,0,1,0,1},{1,1,1,0,1,1,0,1,1,0}};
	cout<<closedIsland(grid);
	return 0;
}
	

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值