LeetCode 305:岛屿数量2

题目

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:

Input: m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]]
Output: [1,1,2,3]
Explanation:

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 grid0 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 grid0 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 grid1 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 grid2 into a land.

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

Follow up:

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

解答

这题是LeetCode 200:岛屿数量的拓展。开始矩阵全0,表示都是水,然后每次增加一块陆地(一个位置置为1),每次要给出当前的岛屿数量。这是一个动态过程,显然每次都进行深搜非常耗时,使用并查集可以满足时间要求。用father数组记录每个位置属于哪个岛屿(不是岛屿则标记为-1)。用cnt记录当前岛屿数量,每次增加一块陆地时先加1,然后判断四个方向的邻居是水还是陆地,需要union时减1。

class Solution {
public:
    vector<int> numIslands2(int m, int n, vector<vector<int>>& positions) {
        vector<int> res;
        int cnt = 0;    // 岛屿数量
        vector<int> father(m * n, -1);    // 开始全是水,初始化为-1
        vector<vector<int>> directions{{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
        for (auto &pos : positions) {
            int id = n * pos[0] + pos[1];
            if (father[id] != -1) {    // 重复出现的位置,无需重新计算,直接将cnt加入结果
                res.push_back(cnt);
                continue;
            }
            father[id] = id;    // 初始化:每块陆地的父节点(所属岛屿)为自己
            ++cnt;
            for (auto direction: directions) {
                int x = pos[0] + direction[0], y = pos[1] + direction[1];
                int cur_id = n * x + y;
                if (x < 0 || x >= m || y < 0 || y >= n || father[cur_id] == -1) // 越界或该位置是水,直接跳过
                    continue;

                // Union操作
                int p = find(father, cur_id), q = find(father, id);
                if (p != q) {
                    father[p] = q;
                    --cnt;
                }
            }
            res.push_back(cnt);
        }
        return res;
    }

    int find(vector<int>& father, int id) {
        if (father[id] != id) {
            father[id] = find(father, father[id]);    // 路径压缩
        } 
        return father[id];
    }
};

参考:https://www.cnblogs.com/grandyang/p/5190419.html

发布了46 篇原创文章 · 获赞 23 · 访问量 3万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览