力扣 leetcode 959. 由斜槓劃分區域 (python)
技術標籤:pythonleetcodeleetcodepython並查集dfs
Topic
在由 1 x 1 方格組成的 N x N 網格 grid 中,每個 1 x 1 方塊由 /、\ 或空格構成。這些字元會將方塊劃分為一些共邊的區域。
(請注意,反斜槓字元是轉義的,因此 \ 用 “\” 表示。)。
返回區域的數目。
Example
Example_1:
輸入:
[
" /",
"/ "
]
輸出:2
解釋:2x2 網格如下:
Example_2
輸入:
[
" /",
" "
]
輸出:1
解釋:2x2 網格如下:
Example_3
輸入:
[
“\/”,
“/\”
]
輸出:4
解釋:(回想一下,因為 \ 字元是轉義的,所以 “\/” 表示 /,而 “/\” 表示 /\。)
2x2 網格如下:
Example_4
輸入:
[
“/\”,
“\/”
]
輸出:5
解釋:(回想一下,因為 \ 字元是轉義的,所以 “/\” 表示 /\,而 “\/” 表示 /。)
2x2 網格如下:
Example_5
輸入:
[
“//”,
"/ "
]
輸出:3
解釋:2x2 網格如下:
Solution
題目比較新穎
但究其本質還是一道需要判斷是否連通的題
所以我們將它轉換為並查集求解
首先判斷被分割成了多少個區域
可以通過判斷有多少個封閉區域進行判斷
分割我們可以看成是連通分量連通的過程
而對於是否封閉
我們可以看作並查集是否成環進行判斷
如果構成了環,則區域封閉
對於判斷是否成環
我們僅需判斷連線時根節點是否相同
若相同則此次連線會導致成環
具體操作:
我們先要把 N x N 網格劃分成 (N + 1) * (N + 1) 個頂點
初始化並查集,並在初始化時設定一個res為最後返回的區域數
然後將頂點在在並查集中設定成節點
先將所有的網格邊緣的節點進行合併
之後遍歷grid進行如下判斷
如果字元為空格 ,跳過,
如果字元為 /,將小網格的 左下 和 右上 兩個頂點合併,如果字元為 \,將小網格的 左上 和 右下 兩個頂點合併。
同時在遍歷的過程中判斷是否成環
若成環區域數加一
若不成環區域數不變
最後返回區域數res即可完成
Code
class UnionFind:
def __init__(self):
self.father = {}
self.res = 1
self.size = [0]
def find(self, x):
root = x
while self.father[root] is not None:
root = self.father[root]
# 路徑壓縮
while x != root:
original_father = self.father[x]
self.father[x] = root
x = original_father
return root
def merge(self, x, y):
root_x, root_y = self.find(x), self.find(y)
if root_x == root_y:
self.res += 1
else:
if self.size[root_x] < self.size[root_y]:
root_x, root_y = root_y, root_x
self.size[root_x] += self.size[root_y]
self.father[root_x] = root_y
def add(self, x):
if x not in self.father:
self.father[x] = None
self.size.append(0)
class Solution:
def regionsBySlashes(self, grid: List[str]) -> int:
n = len(grid)
m = n + 1
uf = UnionFind()
for i in range(m * m + 1):
uf.add(i)
for j in range(m * m):
if j % m == 0 or j % m == m - 1 or j // m == 0 or j // m == m - 1:
uf.merge(j, m * m)
for a in range(n):
for b in range(n):
if grid[a][b]=='/':
uf.merge(m * a + b + 1, m *(a + 1) + b)
elif grid[a][b] == '\\':
uf.merge(m * a + b, m * (a + 1) + b + 1)
return uf.res