959.由斜杠划分区域

4 篇文章 0 订阅
3 篇文章 0 订阅

随手笔记:

 这篇文章讲解leetcode题库中:959.由斜杠划分区域。

题目介绍:(点击此处可以转到leetcode原题)

   题目描述非常简单,用通俗的语言就是,现在有正方形中可以填充“ ”、“\”、“/”,将正方形分成如下图所示的区域。现在有N*N的大正方形中由下面3种小正方形组成。

例如下边左边的图是一个示例,是2*2的大正方形 ,有3个区域。可以将其分解为右侧图案,小正方形1,2,3均为上图第三个小正方形,第四个为上图第一个小正方形。

题目用到的知识:并查集,并查集是非常好用的一种求联连通分量的算法。不会的可以看一下这篇文章,我个人感觉还是不错的。(点此处跳转

并查集可以理解:查找某一个结点的祖先,将不同祖先的节点合并就可以了。

本题是将3种小正方形分为4个小正方形,并且按下图所示顺序标号吗,以上图3个区域的大正方形为例。

单元内合并(按上图顺序来解释):

                     0,1,2,3可以合并为一个,即union(0,1)、(1,2)、(2,3);原来是4个连通分量,现在经过3次合并,数量减3,所以变成一个。

                     0,3;1,2可以合并为两个,即union(0,3)、(1,2);原来是4个连通分量,现在经过2次合并,数量减2,所以变成两个。

                     0,1;2,3可以合并为两个,即union(0,1)、(2,3);原来是4个连通分量,现在经过2次合并,数量减2,所以变成两个。

单元间合并,(可以多画几次图)可以得出两个结论:      

  • 一个格子中最下方的三角形,必然和下面的格子(如果存在)中最上方的三角形连通;

  • 一个格子中最右方的三角形,必然和右边的格子(如果存在)中最左方的三角形连通。

  • 举例:对于下方第一个正方形,其必然与蓝色,橘色相连通,即第一个的序号1与右侧的序号3;第一个的序号2与下方的序号0。

leetcode可通过代码(C++):

class UnionFind{

    private:
        int count;    //计数联通分量数目
        int *parent;  //保存每个节点的祖先
    public:
        UnionFind(int size)    //首先根据数量初始化,并且每个节点的祖先是自己
        {
            count=size;
            parent=new int[size];

            for(int i=0;i<size;i++)
            {   parent[i]=i;    }
        }

        int find(int x)    //找出该节点的祖先,一直找到最上方。(重点,可以树状图辅助理解)
        {
            while(x!=parent[x])
            {
                parent[x]=parent[parent[x]];
                x=parent[x];
            }

            return x;
        }

        void union_xy(int x,int y)    //将两个几点合并
        {
            int root_x=find(x);
            int root_y=find(y);

            if(root_x==root_y)
            {
                return;
            }

//直接找到两个结点的祖先,然后将某一个祖先的祖先由它本身修改为另一个;
//这里是x的祖先是root_x;那么原来root_x的祖先是他本身,现在修改为另一个y的祖先root_y;
//当修改一次,这两个就属于同一个祖先了,连通分量数目就可以减一;
            parent[root_x]=root_y;    
            count--;
        }

        int num()
        {
            return count;
        }
        ~UnionFind()
        {
            delete []parent;
        }
};

class Solution {
public:
    int regionsBySlashes(vector<string>& grid) {
       
//先将string字符转换为char数组。
        int N=grid.size();
        vector<char> grid_2;
        for(int i=0;i<N;i++)
        {
            for(int j=0;j<N;j++)
            {
                grid_2.push_back(grid[i][j]);
            }
        }


        int size=4*N*N;
        int char_num=N*N;
        UnionFind test=UnionFind(size);
//进行单元内的合并。
        for(int i=0;i<char_num;i++)
        {
            if(grid_2[i]==' ')
            {
                test.union_xy(4*i,4*i+1);
                test.union_xy(4*i+1,4*i+2);
                test.union_xy(4*i+2,4*i+3);
            }
            else if(grid_2[i]=='/')
            {
                test.union_xy(4*i,4*i+3);
                test.union_xy(4*i+1,4*i+2);
            }
            else if(grid_2[i]=='\\')
            {
                test.union_xy(4*i,4*i+1);
                test.union_xy(4*i+2,4*i+3);
            }
        }
//单元间合并。
        for(int i=0;i<char_num;i++)
        {
            int j=i%N;
            int k=i/N;
            if(j!=N-1) test.union_xy(4*i+1,4*(i+1)+3);
            if(k!=N-1) test.union_xy(4*i+2,4*(i+N));
        }
    return test.num();
    }
};

有不明白的地方可以私信给我,可以进行进一步讲解。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值