由斜杠划分区域

在由 1 × 1 1 \times 1 1×1 方格组成的 N × N N \times N N×N 网格 g r i d grid grid 中,每个 1 × 1 1 \times 1 1×1 方块由 /\空格构成。这些字符会将方块划分为一些共边的区域。

(请注意,反斜杠字符是转义的,因此 \ 用 “\\” 表示。)。

返回区域的数目。

示例 1:

输入:

[
  " /",
  "/ "
]

输出:2
解释:2x2 网格如下:
在这里插入图片描述

示例 2:

输入:

[
  " /",
  "  "
]

输出:1
解释:2x2 网格如下:
在这里插入图片描述

示例 3:

输入:

[
  "\\/",
  "/\\"
]

输出:4
解释:(回想一下,因为 \ 字符是转义的,所以 “\/” 表示 /,而 “/\” 表示 /\。)
2x2 网格如下:
在这里插入图片描述

示例 4:

输入:

[
  "/\\",
  "\\/"
]

输出:5
解释:(回想一下,因为 \ 字符是转义的,所以 “/\” 表示 /\,而 “\/” 表示 /。)
2x2 网格如下:
在这里插入图片描述

示例 5:

输入:

[
  "//",
  "/ "
]

输出:3
解释:2x2 网格如下:
在这里插入图片描述

提示:

1 < = g r i d . l e n g t h = = g r i d [ 0 ] . l e n g t h < = 30 1 <= grid.length == grid[0].length <= 30 1<=grid.length==grid[0].length<=30
g r i d [ i ] [ j ] grid[i][j] grid[i][j]/\、或

思路

「斜杠」、「反斜杠」把单元格拆分成的 2 2 2 个三角形的形态,在做合并的时候需要分类讨论。根据「斜杠」、「反斜杠」分割的特点,我们把一个单元格分割成逻辑上的 4 个部分。如下图所示:
在这里插入图片描述

我们须要遍历一次输入的二维网格 g r i d grid grid,在 单元格内 和 单元格间 进行合并。

单元格内:

  • 如果是空格:合并 0 、 1 、 2 、 3 0、1、2、3 0123
  • 如果是斜杠:合并 0 、 3 0、3 03,合并 1 、 2 1、2 12
  • 如果是反斜杠:合并 0 、 1 0、1 01,合并 2 、 3 2、3 23
    单元格间:

我们选择在遍历 g r i d grid grid 的每一个单元格的时候,分别向右、向下尝试合并。
在这里插入图片描述

  • 向右:合并 1 1 1 (当前单元格)和 3 3 3(当前单元格右边 1 1 1 列的单元格),上图中红色部分;
  • 向下:合并 2 2 2 (当前单元格)和 0 0 0(当前单元格下边 1 1 1 列的单元格),上图中蓝色部分。
    并查集里连通分量的个数就是题目要求的区域的个数。
class Solution {
public:

    int find(vector<int>&f,int x){
        return f[x]==x?x:f[x]=find(f,f[x]);
    }

    void union1(vector<int>&f,int x,int y){
        x=find(f,x);
        y=find(f,y);
        f[x]=y;
    }

    int regionsBySlashes(vector<string>& grid) {
        int n=grid.size();
        vector<int>f(n*n*4);
        for (int i=0;i<n*n*4;i++){
            f[i]=i;
        }
        for (int i=0;i<n;i++){
            for (int j=0;j<n;j++){
                int idx=i*n+j;
                if (i<n-1){
                    union1(f,idx*4+2,(idx+n)*4);
                }
                if (j<n-1){
                    union1(f,idx*4+1,(idx+1)*4+3);
                }
                if (grid[i][j]=='/'){
                    union1(f,idx*4+1,idx*4+2);
                    union1(f,idx*4,idx*4+3);
                }else if (grid[i][j]=='\\'){
                    union1(f,idx*4+1,idx*4);
                    union1(f,idx*4+2,idx*4+3);
                }else{
                    union1(f,idx*4,idx*4+1);
                    union1(f,idx*4+1,idx*4+2);
                    union1(f,idx*4+2,idx*4+3);
                }
            }
        }
        int res=0;
        for (int i=0;i<n*n*4;i++){
            if (find(f,i)==i) res++;
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值