【leetcode】959. 由斜杠划分区域(regions-cut-by-slashes)(并查集)[中等]

215 篇文章 0 订阅

链接

https://leetcode-cn.com/problems/regions-cut-by-slashes/

耗时

解题:null min
题解:13 min

题意

在由 1 x 1 方格组成的 N x N 网格 grid 中,每个 1 x 1 方块由 /、\ 或空格构成。这些字符会将方块划分为一些共边的区域。

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

返回区域的数目。

提示:

  • 1 <= grid.length == grid[0].length <= 30
  • grid[i][j] 是 ‘/’、’\’、或 ’ '。

思路

并没有想出思路,看题解看会的。。。

正反斜杠,把一个方格划分成 4 个区域,如下所示

 \1/
2 X 0
 /3\

遍历网格中的每个方格,分情况合并这几个区域即可,

  1. 正斜杠 “/” : 合并 1,2 合并 0,3
  2. 反斜杠 “\”: 合并 0,1 合并 2,3
  3. 空格 “ ” : 合并 0,1,2,3

并且每次遍历向右向下合并,使得多个方格连通 :合并 gird[i][j] 的 0 和 gird[i][j+1] 的 2,合并 gird[i][j] 的 3 和 gird[i+1][j] 的 1

时间复杂度: O ( n 2 ) O(n^2) O(n2)

AC代码

class Solution {
public:
    constexpr static int MAXN = 10100;
    int father[MAXN];   //  储存i的father父节点  
    int areacnt = 1;
    
    void makeSet() {  
        for (int i = 0; i < MAXN; i++)   
            father[i] = i;  
    }  

    int findRoot(int x) {   //  迭代找根节点
        int root = x; // 根节点  
        while (root != father[root]) { // 寻找根节点  
            root = father[root];  
        }  
        while (x != root) {  
            int tmp = father[x];  
            father[x] = root; // 根节点赋值  
            x = tmp;  
        }  
        return root;  
    }  

    void Union(int x, int y) {  //  将x所在的集合和y所在的集合整合起来形成一个集合。  
        int a, b;  
        a = findRoot(x);  
        b = findRoot(y);  
        if(a == b) return ;
        father[a] = b;  // y连在x的根节点上   或father[b] = a为x连在y的根节点上
        areacnt--;
    }  
    
    
    int regionsBySlashes(vector<string>& grid) {
        int n = grid.size();
        areacnt = 4*n*n;
        makeSet();
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                int ind = 4*(i*n+j);
                if(grid[i][j] == '/') { // 1 2 | 0 3
                    Union(ind+1, ind+2);
                    Union(ind+0, ind+3);
                }
                else if(grid[i][j] == '\\') { // 1 0 | 2 3
                    Union(ind+1, ind+0);
                    Union(ind+2, ind+3);
                }
                else { // 0 1 2 3
                    Union(ind+0, ind+1);
                    Union(ind+1, ind+2);
                    Union(ind+2, ind+3);
                }
                
                if(j+1 < n) { // j 0, j+1 2
                    Union(ind+0, (ind+4)+2);
                }
                if(i+1 < n) { // i 3, i+1 1
                    Union(ind+3, (ind+4*n)+1);
                }
            }    
        }
        return areacnt;
    }
};

/*
 \1/
2 X 0
 /3\
*/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值