305. 岛屿数量 II

题目:

假设你设计一个游戏,用一个 m 行 n 列的 2D 网格来存储你的游戏地图。

起始的时候,每个格子的地形都被默认标记为「水」。我们可以通过使用 addLand 进行操作,将位置 (row, col) 的「水」变成「陆地」。

你将会被给定一个列表,来记录所有需要被操作的位置,然后你需要返回计算出来 每次 addLand 操作后岛屿的数量。

注意:一个岛的定义是被「水」包围的「陆地」,通过水平方向或者垂直方向上相邻的陆地连接而成。你可以假设地图网格的四边均被无边无际的「水」所包围。

请仔细阅读下方示例与解析,更加深入了解岛屿的判定。

示例:

输入: m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]]
输出: [1,1,2,3]
解析:

起初,二维网格 grid 被全部注入「水」。(0 代表「水」,1 代表「陆地」)

0 0 0
0 0 0
0 0 0
操作 #1:addLand(0, 0) 将 grid[0][0] 的水变为陆地。

1 0 0
0 0 0 Number of islands = 1
0 0 0
操作 #2:addLand(0, 1) 将 grid[0][1] 的水变为陆地。

1 1 0
0 0 0 岛屿的数量为 1
0 0 0
操作 #3:addLand(1, 2) 将 grid[1][2] 的水变为陆地。

1 1 0
0 0 1 岛屿的数量为 2
0 0 0
操作 #4:addLand(2, 1) 将 grid[2][1] 的水变为陆地。

1 1 0
0 0 1 岛屿的数量为 3
0 1 0
拓展:

你是否能在 O(k log mn) 的时间复杂度程度内完成每次的计算?(k 表示 positions 的长度)

 

 

解答:

方法1:

首先我想到的就是dfs,每次加入陆地的时候考察一共有多少岛屿。但不能每次加入陆地都遍历全部矩阵,这样复杂度太高了,需要剪枝。

我的思路是这样:

每个独立的岛屿有独特的编号。每次addland的时候,遍历周边四个位置。

1.如果有一个相邻岛屿,岛屿数--,保存这个相邻岛屿的编号。

2.如果有第二个、甚至第三、四个相邻岛屿,就把之后的相邻的岛屿都用dfs遍历,全部更新为第一个相邻岛屿的编号。每次仍然记得总岛屿数--。

3.如果没有相邻岛屿,直接赋岛屿编号,全局的岛屿编号加一。

代码:

 1 class Solution {
 2 public:
 3     vector<vector<int>> d={{0,-1},{0,1},{1,0},{-1,0}};
 4     int m,n;
 5     bool check(int x,int y){
 6         if(x<0 or x>=m or y<0 or y>=n){
 7             return false;
 8         }
 9         return true;
10     }
11     vector<int> numIslands2(int m, int n, vector<vector<int>>& positions) {
12         this->m=m;
13         this->n=n;
14         vector<vector<int>> matrix(m,vector<int>(n,0));
15         int val=1;//下一个有效的岛屿编号
16         vector<int>res(positions.size(),0);
17         res[0]=1;
18         matrix[positions[0][0]][positions[0][1]]=val++;
19         for(int i=1;i<positions.size();++i){
20             if(matrix[positions[i][0]][positions[i][1]]!=0){//本身就是岛屿
21                 res[i]=res[i-1];
22                 continue;
23             }
24             res[i]=res[i-1]+1;
25             int x=positions[i][0],y=positions[i][1],cur_val=0;
26             // cout<<"addland "<<x<<" "<<y<<endl;
27             for(int j=0;j<4;++j){
28                 int new_x=x+d[j][0],new_y=y+d[j][1];
29                 if(check(new_x,new_y) and matrix[new_x][new_y]!=cur_val){
30                     if(cur_val==0){//相邻的第一片岛屿
31                         cur_val=matrix[new_x][new_y];
32                         res[i]--;
33                     }
34                     else if(matrix[new_x][new_y]!=0){//相邻的第二/三/四片岛屿
35                         dfs(matrix,new_x,new_y,matrix[new_x][new_y],cur_val);
36                         res[i]--;
37                     }
38                 }
39             }
40             matrix[x][y]=cur_val==0?val++:cur_val;
41             // for(auto& vec:matrix){
42             //     for(int x:vec){
43             //         cout<<x<<" ";
44             //     }cout<<endl;
45             // }
46         }
47         return res;
48     }
49 
50     void dfs(vector<vector<int>>& matrix,int x,int y,int ori_val,int new_val){
51         // cout<<"dfs: "<<x<<" "<<y<<" "<<ori_val<<" "<<new_val<<endl;
52         //将ori_val改为new_val
53         matrix[x][y]=new_val;
54         int new_x,new_y;
55         for(int i=0;i<4;++i){
56             new_x=x+d[i][0],new_y=y+d[i][1];
57             if(check(new_x,new_y) and matrix[new_x][new_y]==ori_val){
58                 dfs(matrix,new_x,new_y,ori_val,new_val);
59             }
60         }
61     }
62 };

 

 

方法2:

使用并差集。

代码:

 1 class Solution {
 2 public:
 3     vector<vector<int>> dif={{0,1},{0,-1},{1,0},{-1,0}};
 4     //并差集
 5     vector<int> parents;
 6     int islands = 0;
 7     int getParent(int child){
 8         if(child!=parents[child]){
 9             parents[child]=getParent(parents[child]);
10         }
11         return parents[child];
12     }
13     void merge(int x, int y){
14         int px = getParent(x);
15         int py = getParent(y);
16         if(px != py){
17             parents[px] = py;
18             islands--;
19         } 
20     }
21     vector<int> numIslands2(int m, int n, vector<vector<int>>& positions) {
22         vector<int> res;
23         parents.assign(m*n,-1);
24         for(auto& coordinate:positions){
25             int row=coordinate[0],col=coordinate[1],index=row*n+col;
26             if(parents[index]==-1){//
27                 ++islands;
28                 parents[index]=index;
29                 for(const auto& d:dif){
30                     int new_index=(row+d[0])*n+col+d[1];
31                     if(row+d[0]<m and row+d[0]>=0 and col+d[1]<n and col+d[1]>=0 and parents[new_index]!=-1){
32                         merge(new_index,index);
33                     }
34                 }
35             }
36             res.push_back(islands);
37         }
38         return res;
39     }
40 };

 

 


 

posted @ 2020-02-26 20:46  NeoZy  阅读(961)  评论(0)    收藏  举报