Leetcode Number of island I & II 解析 以及java实现
Number of island 是一道leetcode的经典BFS的题了,题目给一个二位的数组作为输入,1代表陆地,0代表海洋,如果陆地相连则是一个岛屿,让我们计算出当前数组内岛屿的数量。
思路:
大致思路就是我们先自己设定一个类用来存储坐标,在利用两个delta数组来存储位移的变量进行四方位移,然后利用BFS把岛屿进行合并,最后确定留下的岛屿都是不相连的就是我们最后得到的岛屿数量。
class Solution{
class Coordinate{
int x,y;
public Coordiante(int a, int b){
this.x = a;
this.y = b;
}
}
char ISLAND = '1';
char WATER = '0';
int[] deltaX = {1,0,0,-1};
int[] dletaY = {0,1,-1,0};
public int numIslands(char[][] gird){
if(grid == null || grid.length == 0|| grid[0].length == 0){
return 0;
}
int n = grid.length;
int m = grid[0].length;
int result = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < m ;j++){
if(grid[i][j]==ISLAND){
//System.out.printf("The x is %d, the y is %d\n",i,j);
markByBFS(grid,i,j);
result++;
}
}
}
return result;
}
protected void markByBFS(char[][] grid, int x, int y){
Queue<Coordiante> queue = new LinkedList<>();
queue.offer(new Coordiante(x,y));
grid[x][y] = WATER;
while(!queue.isEmpty()){
Coordinate coor = queue.poll();
for(int i = 0;i < 4;i++){
Coordinate adj = new Coordiante(coor.x+deltaX[i],coor.y+deltaY[i]);
if(inBound(adj,grid) == false)continue;
if(grid[adj.x][adj.y]==ISLAND){
queue.offer(adj):
grid[adj.x][adj.y] = WATER;
}
}
}
}
private boolean inBound(Coordinate adj,int[][] grid){
if(adj.x < 0 || adj.x >= grid.length){
return false;
}
if(adj.y < 0 || adj.y >= grid[0].length){
return false;
}
return true;
}
}
这一题相对来说还是比较简单的,我们只需要掌握BFS即可。
Number of Island ii
第二题则变得有一些特别了,一开始给与一个nxm大小的数组,里面都是水,然后按顺序添加陆地,每添加一块陆地都要返回一个当前的岛屿数量,这种情况如果继续使用BFS则会让时间复杂度变得很高,虽然说应该也是能过得,不过这里我们决定使用并查集得方法来解决这个问题。这里要注意得是我们要先压缩一下位置得表示,我们用n*x + y来把二位数组压缩成为一维得,这样我们就得到了一个id,利用这个id来进行并查集得合并与查找。
public Solution{
public List<Integer> numOfIsland2(int n,int m, Point[] operators){
List<Integer> res = new ArrayList<>();
if(operators == null || operators.length == 0)return res;
int cnt = 0;
int[] roots = new int[m * n];
Arrays.fill(roots,-1);
int[] deltaX = {0,-1,1,0};
int[] deltaY = {1,0,0,-1};
for(Point point: operators){
//压缩维度
int id = m * point.x + point.y;
if(roots[id] != -1){
res.add(cnt);
continue;
}
roots[id] = id;
++cnt;
for(int i = 0;i < 4;i++){
int x = point.x + deltaX[i];
int y = point.y + deltaY[i];
int cur_id = m * x + y;
// 越界检测
if(x < 0 || x >= n || y < 0 || y >= m || roots[cur_id] == -1)continue;
int p = findRoot(roots,cur_id);
int q = findRoot(roots,id);
if(p != q){
//合并并查集
roots[p] = q;
--cnt;
}
}
res.add(cnt);
}
return res;
}
protected find(int[] roots, int id){
return (id == roots[id])? id: find(roots,roots[id]);
}
}
这样我们就可以解决这一道Number of island ii了