跟完CS61B的UnionFind不久,所以看到这题第一反应是并查集解。
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入: [ [‘1’,‘1’,‘1’,‘1’,‘0’], [‘1’,‘1’,‘0’,‘1’,‘0’],
[‘1’,‘1’,‘0’,‘0’,‘0’], [‘0’,‘0’,‘0’,‘0’,‘0’] ]
输出: 1
示例 2:
输入: [ [‘1’,‘1’,‘0’,‘0’,‘0’], [‘1’,‘1’,‘0’,‘0’,‘0’],
[‘0’,‘0’,‘1’,‘0’,‘0’], [‘0’,‘0’,‘0’,‘1’,‘1’] ]
输出: 3
解释:
每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-islands
。
时间复杂度和空间复杂度还没算明白,总之提交之后运行效率并不是很好,后面会尝试用DFS和BFS来实现。
class Solution {
/* 1.UnionFind 并查集*/
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0){return 0;}
int row = grid.length;
int col = grid[0].length;
UnionFind uf = new UnionFind(grid);
//coordinates of the neighbors of the object(based on the objects)
int[][] neighbors = new int[][]{{-1,0},{1,0},{0,1},{0,-1}};
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
if (grid[i][j] == '1'){
int oldId = i * col + j;
for (int[] neighbor : neighbors){
int adjRow = i + neighbor[0];
int adjCol = j + neighbor[1];
int newId = adjRow * col + adjCol;
//adjacent coordinates must be valid
if (adjRow >= 0 && adjRow < row && adjCol >= 0 && adjCol < col){
if(grid[adjRow][adjCol] =='1'){
uf.union(oldId, newId);}
}
}
}
}
}
return uf.getCount();
}
private class UnionFind{
int[] parent;
int count;
UnionFind(char[][] grid){
this.count = 0;
int row = grid.length;
int col = grid[0].length;
this.parent = new int[row*col];
//遍历数组里每一个char
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
if (grid[i][j] == '1'){
//给每个陆地编号为父节点, id = i*col+j
parent[i * col + j] = i * col + j;
++count;
}
}
}
}
private int find(int i){
if (parent[i] != i){
parent[i] = find(parent[i]);
}
return parent[i];
}
private void union(int i, int j){
int rootOfi = find(i);
int rootOfj = find(j);
if (rootOfi != rootOfj){
parent[rootOfi] = rootOfj;
--count;
}
}
private int getCount(){
return count;
}
}
}