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

题目链接: 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?


思路: 这题的时间卡的太严了. 基本思路和之前一题给n个结点求有几个不连通的树差不多. 为每个结点设置一个父结点, 

然后新加入的位置向上下左右搜索, 如果搜索到了一块陆地, 那么就看他的最终父结点和当前结点的最终父结点是否相同, 如果相同的话说明他们是连通的, 那么加入当前结点不会让小岛的数量增加, 否则小岛数量维持不变.

如果搜索不到和他相邻的陆地, 那么小岛数量会加1.

我用hash表来动态增加父结点信息会超时, 然后只能用一个数组事先为所有的结点都申请好空间才过.

代码如下:

class Solution {
public:
    int findRoot(vector<int> root, int val)
    {
        while(val != root[val])
        {
            root[val] = root[root[val]];
            val = root[val];
        }
        return val;
    }
    vector<int> numIslands2(int m, int n, vector<pair<int, int>>& positions) {
        vector<int> root(m*n, -1);
        int num = 0;
        vector<int> result;
        for(auto pos: positions)
        {
            int tem = pos.first*n + pos.second;
            root[tem] = tem;
            num++;
            vector<pair<int, int>> dirt{{0,1}, {0,-1}, {1,0}, {-1, 0}};
            for(auto val: dirt)
            {
                int r1, r2, x = tem/n + val.first, y = tem%n + val.second, p = x*n+y;
                if(x < m && x >= 0 && y >=0 && y < n && root[p] != -1)
                {
                    if((r1=findRoot(root, p)) != (r2=findRoot(root, tem)))
                    {
                        num--;
                        root[r2] = r1;
                    }
                }
            }
            result.push_back(num);
        }
        return result;
    }
};
参考: https://leetcode.com/discuss/78856/c-union-find-solution-with-path-compression

你可能感兴趣的:(LeetCode,UNION,array,find)