统计子岛屿(DFS/BFS/并查集)

本文探讨了在解决岛屿问题时,使用深度优先搜索(DFS)、广度优先搜索(BFS)以及并查集的数据结构来判断grid2中的岛屿是否为grid1的子岛屿。作者通过实例展示了如何利用这些算法进行遍历和标记,最后计算子岛屿数量。
摘要由CSDN通过智能技术生成

         又是我们熟悉的岛屿问题,依照该题题意,我们知道,如果grid2的岛屿不是grid1的子岛屿的话,肯定grid2中出现的1在grid1的相同位置上不是1,根据这一点,我们可以这样: 我们遍历grid2,如果遇到1就搜索这个岛屿,在搜索的过程中同时比对相同位置grid1和grid2的情况,如果出现不一样的情况,我们就做个“记号”,记得我们搜索过的地方要“改变”或者用一个数组记录下,搜索完毕后,我们就根据这个记号判断该岛屿是不是子岛屿并且计数

        1.DFS

class Solution {
public:
 int n, m, tx, ty, sign = 1, ans = 0, nextt[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
void dfs(vector<vector<int>>& grid1, vector<vector<int>>& grid2, int x, int y)
{
	if (grid2[x][y])
	{
		if (grid1[x][y] != grid2[x][y])//判断相同位置的情况
		{
			sign = 1;
		}
        grid2[x][y]=0;
		for (int i = 0; i < 4; i++)
		{
			tx = x + nextt[i][0];
			ty = y + nextt[i][1];
			if (tx < 0 || ty < 0 || tx >= n || ty >= m || grid2[tx][ty] == 0 )
			{
				continue;
			}
			dfs(grid1, grid2, tx, ty);
		}
	}
}

int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
	n = grid2.size();
	m = grid2[0].size();
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			sign = 0;//重新初始化“记号”
			if (grid2[i][j] == 1)
			{
				dfs(grid1, grid2, i, j);
				if (!sign)//判断记号情况
				{
					ans++;
				}
			}
		}
	}

	return ans;
}
};

        2.BFS(思路与上述一致)

class Solution {
public:
 int n, m, tx, ty, sign = 0, ans = 0, nextt[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
 int book[500][500]={0};

void bfs(vector<vector<int>>& grid1, vector<vector<int>>& grid2, int x, int y)
{
    queue<pair<int,int>>q;
    q.push({x,y});
    pair<int,int> now;
    while(!q.empty())
    {
        now=q.front();
        int x=now.first;
        int y=now.second;
        q.pop();
        if(grid1[x][y]!=grid2[x][y])
        {
            sign=1;
        }
        book[x][y]=1;
        for(int i=0;i<4;i++)
        {
            tx=x+nextt[i][0];
            ty=y+nextt[i][1];
            if(tx<0||ty<0||tx>=n||ty>=m||grid2[tx][ty]==0||book[tx][ty])
            {
                continue;
            }
            q.push({tx,ty});
            book[tx][ty]=1;
        }
    }
}

int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
	n = grid2.size();
	m = grid2[0].size();
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			sign = 0;
			if (grid2[i][j] == 1&&!book[i][j])
			{
				bfs(grid1, grid2, i, j);
				if (!sign)
				{
					ans++;
				}
			}
		}
	}

	return ans;
}
};

        3.并查集

该思路稍微与上面有所不同,我们先遍历数组,如果找到一个点(在grid1中是0而在grid2中是1的),那么这个点代表的岛屿肯定不是子岛屿,我们就搜索这个岛屿,并且把它们都变成0,

那么剩下的岛屿就肯定都是子岛屿啦,我们就遍历数组,遇到1,就直接把它和它相邻的1并起来,

最后数一数有多少个“根”就行了

class Solution {
public:
    vector<int> fa;
    int row, col, tx, ty, nextt[4] [2] = { {0,1},{1,0},{0,-1},{-1,0} };
    void init(int n)//初始化
    {
        fa.resize(n);
        for (int i = 0; i < n; ++i)
        {
            fa[i] = i;
        }
    }
    vector<pair<int, int>> directions = { {1,0},{-1,0},{0,1},{0,-1} };
    int find(int x)//找 根
    {
        if (fa[x] == x)
        {
            return x;
        }
        else
            return find(fa[x]);
    }
    void merge(int i, int j)//并
    {
        int x = find(i), y = find(j);
        if (x == y)
        {
            return;
        }
        fa[x] = y;
    }
    void dfs(vector<vector<int>>& grid1, vector<vector<int>>& grid2, int i, int j)
    {
        for (const auto& dir : directions)
        {
            int newi = i + dir.first, newj = j + dir.second;
            if (newi >= 0 && newi < row && newj >= 0 && newj < col && grid2[newi][newj] == 1)
            {
                grid2[newi][newj] = 0;
                dfs(grid1, grid2, newi, newj);

            }
        }
    }
    int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2)
    {
        row = grid1.size(), col = grid1[0].size();
        init(row * col+10);

        for (int i = 0; i < row; ++i)
        {
            for (int j = 0; j < col; ++j)
            {
                if (grid1[i][j] == 0 && grid2[i][j] == 1)
                {
                    grid2[i][j] = 0;
                    dfs(grid1, grid2, i, j);
                }
            }
        }

        //合并
        for (int i = 0; i < row; ++i)
        {
            for (int j = 0; j < col; ++j)
            {
                if (grid2[i][j] == 1)
                {
                    for (int z = 0; z < 4; z++)
                    {
                        tx = i + nextt[z][0];
                        ty = j + nextt[z][1];
                        if (tx < 0 || ty < 0 || tx >= row || ty >= col || grid2[tx][ty] == 0)
                        {
                            continue;
                        }
                        merge(tx * col + ty,i * col + j);
                    }
                }
                else
                {
                    merge(i * col + j, row*col);//注意这里要把那些0都并到另一个地方去
                }
            }
        }

        int ans = 0;//grid2 中 子岛屿 的 数目 
        for (int i = 0; i < row * col; ++i)
        {
            if (  i == fa[i])
                ++ans;
        }
        return ans;

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZZWWWFFF_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值