959. 由斜杠划分区域

9 篇文章 0 订阅
7 篇文章 0 订阅

959. 由斜杠划分区域

在由 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] 是 '/'、'\'、或 ' '。


基本思路:求斜杠划分区域个数,容易想到并查集,但是怎么把现在的模型转换成可以使用并查集的情况,我们知道,一个单元格,最多被分为四分,所以我们可以把单元格划分为4份,然后根据情况连接。具体如上图所示

  • 等价于把一个格子映射到4个区域0,1,2,3
  • 注意,当前格子<i,j>的区域1必定和上一行<i-1,j>的区域3相连;当前格子<i,j>的区域0必定和左边<i,j-1>的区域2相连
  • 如果是/,那么0,1相连,2,3相连;如果是\,那么1,2相连,0,3相连

    vector<int> parent,psize;
    int count=0;
    int find(int x){
        return x==parent[x]?x:parent[x]=find(parent[x]);
    }
    bool connect(int x,int y){
        int rx=find(x);
        int ry=find(y);
        if(rx==ry)
            return false;
        
        if(psize[rx]<psize[ry])
            swap(rx,ry);
        parent[ry]=rx;
        psize[rx]+=psize[ry];
        count--;
        return true;
    }
    void init(int n){
        count=n;
        parent.resize(n,0);
        psize.resize(n,1);
        for(int i=0;i<n;i++)
            parent[i]=i;
    }
    int regionsBySlashes(vector<string>& grid) {
        int n=grid.size();
        auto getPos=[&n](int row,int col,int i)->int{return(row*n+col)*4+i;};
        init(4*n*n);
        for(int i=0;i<n;i++){

            for(int j=0;j<n;j++){
                if(i>0){
                    connect(getPos(i,j,1),getPos(i-1,j,3));  //与上部连接
                } 
                if(j>0){
                    connect(getPos(i,j,0),getPos(i,j-1,2));  //与左部连接
                }
                if(grid[i][j]=='/'){
                    connect(getPos(i,j,0),getPos(i,j,1));
                    connect(getPos(i,j,2),getPos(i,j,3));
                }
                else if(grid[i][j]=='\\'){
                    connect(getPos(i,j,1),getPos(i,j,2));
                    connect(getPos(i,j,0),getPos(i,j,3));
                }
                else{
                    connect(getPos(i,j,0),getPos(i,j,1));
                    connect(getPos(i,j,1),getPos(i,j,2));
                    connect(getPos(i,j,2),getPos(i,j,3));
                }

            }
            
        }
        return count;
    }

 基本思路2:我们也可以用dfs/bfs的方式,此时我们可以把一个单元格,映射到3*3的方格中,其中斜线代表的是中间的单元格为1

    void dfs(vector<vector<int>> &ng,int x,int y){
        if(x<0||x>=ng.size()||y<0||y>=ng.size()||ng[x][y])
            return;
        ng[x][y]=1;
        dfs(ng,x-1,y);
        dfs(ng,x+1,y);
        dfs(ng,x,y-1);
        dfs(ng,x,y+1);
    }
    int regionsBySlashes(vector<string>& grid) {
        int n=grid.size();
        int count=0;
        vector<vector<int>> ng(3*n,vector<int>(3*n,0));//grid->ng映射

        //初始化ng,把/,\限制条件加上
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]=='/'){
                    ng[3*i][3*j+2]=ng[3*i+1][3*j+1]=ng[3*i+2][3*j]=1;
                }
                if(grid[i][j]=='\\'){
                    ng[3*i][3*j]=ng[3*i+1][3*j+1]=ng[3*i+2][3*j+2]=1;
                }
            }
        }


        //dfs遍历
        for(int i=0;i<ng.size();i++){
            for(int j=0;j<ng.size();j++){
                if(ng[i][j]==0){
                    count++;
                    dfs(ng,i,j);
                }
            }
        }
        return count;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值