---
# System prepended metadata

title: 0827. Making A Large Island
tags: [Leetcode, FaceBook, Union Find, Island, Hard]

---

# 0827. Making A Large Island
###### tags: `Leetcode` `FaceBook` `Hard` `Union Find` `Island`
Link: https://leetcode.com/problems/making-a-large-island/
## 思路
并查集先合并所有island，然后遍历所有水域，对于每一个水域上下左右如果有岛，并且father不同，那么这些岛的面积求和+1，就是现在的岛屿面积

这里要注意的是一开始合并的时候因为是用边合并，所以这种状况是考虑不到单个一个点的island的，所以
```
fa[i] = i
size[i] = grid[i/C][i%C]==1?1:0
```
保证每个节点都记录下来
其次要注意并查集的两个function 
- combine function里面不要漏掉如果两个父节点相同，直接return
- find function里面最后```return fa[a] = find(fa[a])```而不是```fa[a] = find(a)```
- 然后由于原本的方法没有考虑到没有水的情况（不用合并，直接拿最大岛屿），所以加上了第30行```maxArea = Math.max(maxArea, size[i*C+j]);```
- 第40行```if(!father.contains(find(nei)))```一定不能写```if(!father.contains(nei))```debug很久才找到
## Code
```java=
class Solution {
    private int[] fa, size;
    public int largestIsland(int[][] grid) {
        int R = grid.length;
        int C = grid[0].length;
        fa = new int[R*C];
        size = new int[R*C];
        for(int i = 0;i < R*C;i++){
            fa[i] = i;
            size[i] = grid[i/C][i%C]==1?1:0;
        }
        for(int i = 0;i < R;i++){
            for(int j = 0;j < C;j++){
                if(grid[i][j] == 1){
                    if(j+1<C && grid[i][j+1] == 1){
                        combine(grid, i*C+j, i*C+j+1);
                    }
                    if(i+1<R && grid[i+1][j] == 1){
                        combine(grid, i*C+j, (i+1)*C+j);
                    }
                }
            }
        }
        int maxArea = 0;
        for(int i = 0;i < R;i++){
            for(int j = 0;j < C;j++){
                if(grid[i][j] == 0){
                    maxArea = Math.max(maxArea, getArea(i,j,grid));
                }
                maxArea = Math.max(maxArea, size[i*C+j]);
            }
        }
        return maxArea;
    }
    private int getArea(int x, int y, int[][] grid){
        List<Integer> neighbor = getneighbor(x,y,grid);
        Set<Integer> father = new HashSet<>();
        int area = 0;
        for(int nei:neighbor){
            if(!father.contains(find(nei))){
                father.add(find(nei));
                area+=size[find(nei)];
            }
        }
        return area+1;
    }
    private List<Integer> getneighbor(int x, int y, int[][] grid){
        int R = grid.length;
        int C = grid[0].length;
        List<Integer> ans = new ArrayList<>();
        if(x-1>=0 && grid[x-1][y]==1) ans.add((x-1)*C+y);
        if(x+1<R && grid[x+1][y]==1) ans.add((x+1)*C+y);
        if(y-1>=0 && grid[x][y-1]==1) ans.add(x*C+y-1);
        if(y+1<C && grid[x][y+1]==1) ans.add(x*C+y+1);
        return ans;
    }
    private int find(int a){
        if(fa[a] == a) return a;
        else return fa[a] = find(fa[a]);
    }
    private void combine(int[][] grid, int a, int b){
        a = find(a);
        b = find(b);
        if(a == b) return;
        if(size[a]<size[b]){
            fa[a] = b;
            size[b]+=size[a];
        }
        else{
            fa[b] = a;
            size[a]+=size[b];
        }
    }
}
```