leetcode:由斜杠划分区域

题目来源:力扣

题目描述:

在由 1 x 1 方格组成的 N x N 网格 grid 中,每个 1 x 1 方块由 /、\ 或空格构成。这些字符会将方块划分为一些共边的区域。
(请注意,反斜杠字符是转义的,因此 \ 用 “\” 表示。)。
返回区域的数目。
=============================================
示例 1:
输入:
[
" /",
“/ "
]
输出:2
解释:2x2 网格如下:
在这里插入图片描述
示例 2:
输入:
[
" /”,
" "
]
输出:1
解释:2x2 网格如下:
在这里插入图片描述
示例 3:
输入:
[
“\/”,
“/\”
]
输出:4
解释:(回想一下,因为 \ 字符是转义的,所以 “\/” 表示 /,而 “/\” 表示 /\。)
2x2 网格如下:
在这里插入图片描述
示例 4:
输入:
[
“/\”,
“\/”
]
输出:5
解释:(回想一下,因为 \ 字符是转义的,所以 “/\” 表示 /\,而 “\/” 表示 /。)
2x2 网格如下:
在这里插入图片描述
示例 5:
输入:
[
“//”,
"/ "
]
输出:3
解释:2x2 网格如下:
在这里插入图片描述
1 <= grid.length == grid[0].length <= 30
grid[i][j] 是 ‘/’、’’、或 ’ '。

审题:

这道题本质上是计算连通分量个数,难点在于理解题意以及确定哪些元素是相连的.

理解题意:

题目使用字符串表示对正方形的划分,若grid.length == n,则表示将当前单元格划分为 n 2 n^2 n2个小正方形单元格,然后在将每一个小正方形单元格划分两个三角形.如果使用/划分,则当前小正方形被划分为左上,右下两个三角形,如果使用\划分,则当前三角形被划分为左下,右上两个三角形.如果使用空格,则表示不对当前小正方形进行划分.题目要求判断划分的区域个数,实际上就是要求计算所有小三角形中的连通分量个数.

判断连通性:

注意到一个小三角形可能属于一下四种方位之一,左下,左上,右下,右上.对于未被划分的小三角形,可以将其视作左上,右下划分,不过这两个小三角形是连通的.如果当前小正方形使用/\划分,则被划分后的两个小三角形不是连通的.对于每一个小三角形,除与其位于同一正方形的三角形外,其最多与周围两个三角形连通.例如,位于左下的三角形,如果其左侧有正方形,则其与左侧正方形的一个三角形相连通(右上或右下),如果其下方有正方形,则其余下方正方形的一个三角形相连通(左上或右上).

在理解以上两点后,我们便可以考虑如何计算图中的连通分量个数,此处我们使用并查集计算图中的连通分量个数.

java算法实现:

class Solution {
     
	//定义常量表示四个方位
    final int left_up = 1;
    final int left_down = 2;
    final int right_up = 3;
    final int right_down = 4;

	//将三维坐标转化为一维坐标
    private int loc(int x, int y, int z, int gridSize){
     
        return (x*gridSize+y)*2+z;
    }

	//判断给定的方位是否为左侧,左上或左下
    private boolean isLeft(int x){
     
        return x == 1 || x == 2;
    }

    private boolean isRight(int x){
     
        return x == 3 || x == 4;
    }

    private boolean isUp(int x){
     
        return x == 1 || x == 3;
    }

    private boolean isDown(int x){
     
        return x == 2 || x == 4;
    }

	//使用并查集将当前位置grid[i][j][k]处的三角形与其相邻的两个三角形进行相连
    private void unionAdj(UnionFind uf, int[][][] grid, int i, int j, int k){
     
        if(grid[i][j][k] == left_up){
     
            if(j > 0){
      //左边的右三角形
                if(isRight(grid[i][j-1][0])) //左边
                    uf.union(loc(i, j-1, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i, j-1, 1, grid.length), loc(i, j, k, grid.length));
            }
            if(i > 0){
     //上边的下三角形
                if(isDown(grid[i-1][j][0])) //上边
                    uf.union(loc(i-1, j, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i-1, j, 1, grid.length), loc(i, j, k, grid.length));
            }
        }
        else if(grid[i][j][k] == left_down){
     
            if(j > 0){
     //左边的右三角形
                if(isRight(grid[i][j-1][0])) //左边的右三角形
                    uf.union(loc(i, j-1, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i, j-1, 1, grid.length), loc(i, j, k, grid.length));
            }
            if(i < grid.length-1){
      //下边的上三角形
                if(isUp(grid[i+1][j][0])) //下边的上三角形
                    uf.union(loc(i+1, j, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i+1, j, 1, grid.length), loc(i, j, k, grid.length));
            }
        }
        else if(grid[i][j][k] == right_up){
     
            if(i > 0){
     
                if(isDown(grid[i-1][j][0])) //上边的下三角形
                    uf.union(loc(i-1, j, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i-1, j, 1, grid.length), loc(i, j, k, grid.length));
            }
            if(j < grid.length-1){
     
                if(isLeft(grid[i][j+1][0])) //右边
                    uf.union(loc(i, j+1, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i, j+1, 1, grid.length), loc(i, j, k, grid.length));
            }
        }
        else if(grid[i][j][k] == right_down){
     
            if(i < grid.length-1){
      //下边
                if(isUp(grid[i+1][j][0]))
                    uf.union(loc(i+1, j, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i+1, j, 1, grid.length), loc(i, j, k, grid.length));
            }
            if(j < grid.length-1){
      //右边
                if(isLeft(grid[i][j+1][0]))
                    uf.union(loc(i, j+1, 0, grid.length), loc(i, j, k, grid.length));
                else
                    uf.union(loc(i, j+1, 1, grid.length), loc(i, j, k, grid.length));
            }
        }
    }

	//定义并查集类
    class UnionFind{
     
        int[] id;
        int count;
        public UnionFind(int num){
     
            id = new int[num];
            for(int i = 0; i < num; i++)
                id[i] = i;
            count = num;
        }

        public int find(int i){
     
            return id[i];
        }

        public void union(int i, int j){
     
            //System.out.printf("%d, %d\n", i, j);
            if(find(i) == find(j)) //已经在同一连通分量中
                return;
            //将所有连通分量i中的元素全部连接到i所在的连通分量中
            int jId = find(j);
            for(int k = 0; k < id.length; k++){
     
                if(find(k) == jId)
                    id[k] = find(i);
            }
            count--; //连通分量减1
        }

        public int count(){
     
            return count;
        }
    }

    public int regionsBySlashes(String[] grid) {
     
        int[][][] smallGrid = new int[grid.length][grid.length][2];
        
        //使用并查集搜索连通分量个数
        UnionFind uf = new UnionFind(grid.length*grid.length*2);

        for(int i = 0; i < grid.length; i++){
     
            for(int j = 0; j < grid[i].length(); j++){
     
                if(grid[i].charAt(j) == '/'){
     
                    //划分为左上,右下两部分
                    smallGrid[i][j][0] = left_up;
                    smallGrid[i][j][1] = right_down;
                }
                else if(grid[i].charAt(j) == ' '){
     
                    smallGrid[i][j][0] = left_up;
                    smallGrid[i][j][1] = right_down;
                    //当前两个三角形是连通的
                    uf.union(loc(i, j, 0, grid.length), loc(i, j, 1, grid.length));
                }
                else{
      // "\\"
                    smallGrid[i][j][0] = left_down;
                    smallGrid[i][j][1] = right_up;
                }
            }
        }

		//并查集连接
        for(int i = 0; i < grid.length; i++){
     
            for(int j = 0; j < grid.length; j++){
     
                unionAdj(uf, smallGrid, i, j, 0);
                unionAdj(uf, smallGrid, i, j, 1);
            }
        }
        return uf.count();
    }
}

你可能感兴趣的:(leetcode,#,并查集)