[leetcode] 305. Number of Islands II 解题报告

这篇博客介绍了如何使用并查集解决LeetCode中的305题——Number of Islands II。文章详细解释了如何将二维数组转换为一维,并通过并查集算法,跟踪每个操作后岛屿的数量。在每次addLand操作时,会检查新陆地是否与现有岛屿相邻,若相邻则合并岛屿,调整岛屿计数。博客提供了问题的解决方案和思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接: https://leetcode.com/problems/number-of-islands-ii/

A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand operation which turns the water at position (row, col) into a land. Given a list of positions to operate, count the number of islands after each addLand operation. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example:

Given m = 3, n = 3positions = [[0,0], [0,1], [1,2], [2,1]].
Initially, the 2d grid grid is filled with water. (Assume 0 represents water and 1 represents land).

0 0 0
0 0 0
0 0 0

Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.

1 0 0
0 0 0   Number of islands = 1
0 0 0

Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.

1 1 0
0 0 0   Number of islands = 1
0 0 0

Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.

1 1 0
0 0 1   Number of islands = 2
0 0 0

Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.

1 1 0
0 0 1   Number of islands = 3
0 1 0

We return the result as an array: [1, 1, 2, 3]

Challenge:

Can you do it in time complexity O(k log mn), where k is the length of the positions?


思路: 一道并查集的题目, 并无什么陷阱. 主要思路还是为每一个位置初始化一个父结点, 因为是一个二维数组, 比较方便的方式是二维转化为一维. 也就是每一个位置的父结点设置(x*n+y), 其中(x, y)为其位置坐标. 然后每次插入一个新元素的时候查上下左右地图是不是有相邻的陆地, 当然在此之前还需要建立一张二维的地图用来维护地图的状态. 这样如果新添加的一个点的时候默认小岛数量增加1, 但是如果这个新添加的陆地有相邻的陆地, 就将其合并成一块陆地, 并且小岛数量-1. 因为他有上下左右四个方向, 所以有可能当前点连接了之前并不相连的小岛, 在当前结点碰到第一个相邻的陆地的时候, 他被并入了那块陆地, 如果之后他碰到了另一个小岛和他属于不同的小岛, 则还要合并两个小岛, 又会让小岛数量-1. 

代码如下:

class Solution {
public:
    vector<int> numIslands2(int m, int n, vector<pair<int, int>>& positions) {
        vector<vector<int>> mp(m, vector<int>(n, 0));
        vector<int> result;
        int num = 0;
        vector<int> par(m*n);
        for(int i = 0; i < m*n; i++) par[i] = i;
        for(auto val: positions)
        {
            vector<pair<int, int>> dir{{1,0}, {-1,0}, {0,1}, {0,-1}};
            for(auto val2: dir)
            {
                int x =val.first, y =val.second, px =x+val2.first, py =y+val2.second;
                if(px<0 || px>=m || py<0 || py>=n || !mp[px][py]) continue;
                int par1 = x*n + y, par2 = px*n + py;
                while(par[par1] != par1) par[par1] = par[par[par1]], par1 = par[par1];
                while(par[par2] != par2) par[par2] = par[par[par2]], par2 = par[par2];
                if(par1 != par2) par[par2] = par1, num--;
            }
            mp[val.first][val.second] = 1;
            result.push_back(++num);
        }
        return result;
    }
};






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值