题解:Leetcode959--由斜杠划分区域(并查集)

题目概述:

在由 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.将每个方块划分成上下左右四小方块

2.对于每一个大方块里的小方块,根据字符是/还是\还是空格,进行不同的合并操作

3.对于大方块与大方块之间,左右两个小方块可以合并,上下两个小方块可以合并

4.并查集的使用:如果发现合并的时候,合并的两个小方块的父亲都是同一个,证明二者其实已经合并过的(二者已经联通),不需要再次合并


代码:

 1 class Solution {
 2 public:
 3     int father[3605];//记录每个小方块的“父亲” 
 4     int number;//记录区域数量 
 5     int square[3605];//记录小方块 
 6     int find(int x)//寻找小方块的父亲 
 7     {
 8         if(father[x]==x)//如果它本身的父亲就是自己,那么找到头了,返回 
 9         {
10             return x;
11         }
12         else//如果父亲不是自己,则未寻找到底,继续寻找,并且把父亲记录更新成根节点 
13         {
14             father[x]=find(father[x]);
15             return father[x];
16         }
17     }
18     void gettogether(int a,int b)//合并 
19     {
20         if(find(a)==find(b))//如果二者的父亲是同一个,则二者已经联通,不需要再次合并 
21         {
22             return;
23         }
24         //这里涉及到一个问题,为什么合并的时候都要find一次而不是直接比较father[a]和father[b]呢?因为合并之后,某个小方块的father不一定是他的最终father,具有滞后性!重新find可以更新他的father! 
25         else//如果不是同一个,那么先寻找到a的父亲,再让a的父亲成为b的父亲的儿子,这样a的父亲的一家子都是b的父亲的儿子了,这样就联通起来了 
26         {
27             a=find(a);
28             father[a]=find(b);
29             number--;//数量减一 
30             return;
31         }
32         
33     }
34     int regionsBySlashes(vector<string>& grid) {
35         number=grid.size()*grid.size()*4; 
36         for(int i=0;i<=3604;i++)//最开始让每个小方块的父亲都是自己 
37         {
38             father[i]=i;
39             square[i]=i;
40         }
41         for(int i=0;i<grid.size();i++)
42         {
43             for(int j=0;j<grid.size();j++)
44             {
45                 if(i<grid.size()-1)//如果不是最后一行,则该大方块可以和下面的大方块合并 
46                 {
47                     gettogether(square[i*grid.size()*4+j*4+2],square[(i+1)*grid.size()*4+j*4]);
48                 }
49                 if(j<grid.size()-1)//如果不是最后一列,则该大方块可以和右边的大方块合并 
50                 {
51                     gettogether(square[i*grid.size()*4+j*4+1],square[i*grid.size()*4+(j+1)*4+3]);
52                 }
53                 if(grid[i][j]=='/')//‘/’的合并方式 
54                 {
55                     gettogether(square[i*grid.size()*4+j*4],square[i*grid.size()*4+j*4+3]);
56                     gettogether(square[i*grid.size()*4+j*4+1],square[i*grid.size()*4+j*4+2]);
57                 }
58                 else if(grid[i][j]=='\\')//‘\’的合并方式 
59                 {
60                     gettogether(square[i*grid.size()*4+j*4],square[i*grid.size()*4+j*4+1]);
61                     gettogether(square[i*grid.size()*4+j*4+2],square[i*grid.size()*4+j*4+3]);
62                 }
63                 else if(grid[i][j]==' ')//空白的合并方式 
64                 {
65                     gettogether(square[i*grid.size()*4+j*4],square[i*grid.size()*4+j*4+1]);
66                     gettogether(square[i*grid.size()*4+j*4+2],square[i*grid.size()*4+j*4+3]);
67                     gettogether(square[i*grid.size()*4+j*4],square[i*grid.size()*4+j*4+2]);
68                 }
69             }
70         }
71         return number;//返回数量 
72     }
73 };

 

posted @ 2020-11-29 21:22  _厨师沙拉  阅读(141)  评论(0)    收藏  举报