[LeetCode解题报告] 959. 由斜杠划分区域
一、 题目
1. 题目描述
在由 1 x 1
方格组成的 n x n
网格 grid
中,每个 1 x 1
方块由 '/'
、'\'
或空格构成。这些字符会将方块划分为一些共边的区域。
给定网格 grid
表示为一个字符串数组,返回 区域的数量 。
请注意,反斜杠字符是转义的,因此 '\'
用 '\\'
表示。
示例 1:
输入:grid = [" /“,”/ "]
输出:2
示例 2:
输入:grid = [" /“,” "]
输出:1
示例 3:
输入:grid = [“/\”,“\/”]
输出:5
解释:回想一下,因为 \ 字符是转义的,所以 “/\” 表示 /\,而 “\/” 表示 /。
提示:
n == grid.length == grid[i].length
1 <= n <= 30
grid[i][j]
是'/'
、'\'
、或' '
Related Topics
- 深度优先搜索
- 广度优先搜索
- 并查集
- 图
- 👍 305
- 👎 0
2. 原题链接
链接: 959. 由斜杠划分区域
二、 解题报告
1. 思路分析
方法一、并查集
- 把每条边加入并查集,那么空格代表四个边可连通,/代表上边左边通、右边下边通,同理\代表左下通、右上通
- 最后计数祖宗节点即可
方法二、DFS连通分量
- 把每个格子扩展成3×3的格子,计算连通分量即可。
2. 复杂度分析
每个格子只会计算一次,因此两种的复杂度都是O(n2)
3.代码实现
并查集
。
class Solution:
def regionsBySlashes(self, grid: List[str]) -> int:
n = len(grid)
# (x,y,0) 左端点代表一个横边,tag0
# (x,y,1) 用上端点代表一个竖边,tag1
def top(i,j): # 正方形i,j的顶边
return (i,j,0)
def bottom(i,j): # 低边
return (i+1,j,0)
def left(i,j): # 左边
return (i,j,1)
def right(i,j): # 右边
return (i,j+1,1)
fathers = {}
# 初始化,把所有边加入并查集
for i in range(n):
for j in range(n):
fathers[top(i,j)] = top(i,j)
fathers[left(i,j)] = left(i,j)
for i in range(n):
fathers[right(i,n-1)] = right(i,n-1)
fathers[bottom(n-1,i)] = bottom(n-1,i)
def find_father(x):
if fathers[x] != x:
fathers[x] = find_father(fathers[x])
return fathers[x]
def union(x,y):
x = find_father(x)
y = find_father(y)
fathers[x] = y
for i in range(n):
for j in range(n):
if grid[i][j] == ' ': # 四个边都连起来
union(top(i,j),bottom(i,j))
union(top(i,j),left(i,j))
union(top(i,j),right(i,j))
elif grid[i][j] == '/': # 上左连,下右连
union(top(i,j),left(i,j))
union(bottom(i,j),right(i,j))
else: # 上右连,下左连
union(top(i,j),right(i,j))
union(bottom(i,j),left(i,j))
ans = set([find_father(x) for x in fathers ])
# print(fathers)
# print(ans)
return len(ans)
DFS
class Solution:
def regionsBySlashes(self, grid: List[str]) -> int:
n = len(grid)
m = 3*n
# 把每个小格子转化成3*3的格子,求连通分量
new_grid = [[0]*m for _ in range(m)]
for i in range(n):
for j in range(n):
if grid[i][j] == ' ':
pass
elif grid[i][j] == '/':
new_grid[i*3][j*3+2] = 1
new_grid[i*3+1][j*3+1] = 1
new_grid[i*3+2][j*3] = 1
else:
new_grid[i*3][j*3] = 1
new_grid[i*3+1][j*3+1] = 1
new_grid[i*3+2][j*3+2] = 1
def dfs(x,y):
if 0 <= x < m and 0 <= y < m and new_grid[x][y] == 0:
new_grid[x][y] = 1
dfs(x+1,y)
dfs(x-1,y)
dfs(x,y+1)
dfs(x,y-1)
ans = 0
for i in range(m):
for j in range(m):
if new_grid[i][j] == 0:
ans += 1
dfs(i,j)
return ans
三、 本题小结
- 计算连通分量,需要一点技巧。我一开始想到的是并查集。