1. 解题思路
这一题看起来搞定的人不多,不过多半是因为繁琐吧。
这道题思路上其实非常的直接,就是一个递归的方法,我们可以从连接关系当中快速地找到所有的角节点,边节点以及内部节点,然后通过角节点和边节点,我们可以还原出矩阵的4条边,然后通过内部节点我们可以使用递归的方法求得其构成的内部矩阵,最后我们将得到的4条边拼接到内部矩阵的外侧即可。
整体来说,我们可以将函数抽象为4步:
- 找出所有的角节点,边节点以及内部节点
- 还原矩阵的边
- 计算内部矩阵
- 将2中计算得到的边拼接到3中得到的内部矩阵外侧
每一步其实都没有特别复杂,但是会有一些特殊情况,多少会有些复杂和繁琐。比如说:
- 找角节点,边节点以及内部节点的时候,通常情况下其度数分别为2、3、4,不过如果矩阵仅一行,那么其对应的度数就是1、2、3,而如果矩阵仅一个点,那么其度数只有1。
- 还原矩阵的边的时候,通常矩阵有4条边,每条边除端节点之外均为边节点,且相互间不关联。但是如果矩阵只有1行或者两行,上述说法就会有一点问题,需要单独考虑一下。
- 如果矩阵只有1行或者两行,那么他是没有内部矩阵的,因此我们直接对齐矩阵的边然后返回即可;
- 拼接矩阵的边的时候,需要首先对齐找到矩阵的4条边的上下左右位置关系,然后进行拼接。
Anyway,总之就是实现上比较复杂,但是整体难度不大,有兴趣的读者可以试试,没兴趣的话这道题pass我觉得也没啥……
2. 代码实现
给出python代码实现如下:
class Solution:
def constructGridLayout(self, n: int, edges: List[List[int]]) -> List[List[int]]:
def classify_points(points, edges):
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
cnt = min(len(graph[u]) for u in points)
corners = {u for u in points if len(graph[u]) == cnt}
sides = {u for u in points if len(graph[u]) == cnt+1}
inners = {u for u in points if len(graph[u]) == cnt+2}
return graph, corners, sides, inners
def construct_grid_sides(graph, corners, sides):
if len(sides) == 0:
u = list(corners)[0]
grid_sides = [[u, graph[u][0]]]
if len(graph[u]) > 1:
v = graph[u][1]
w = [i for i in graph[v] if i != u][0]
grid_sides.append([v, w])
return grid_sides
elif any(u in corners for c in corners for u in graph[c]):
u = list(corners)[0]
v = [i for i in graph[u] if i in corners][0]
unext = [i for i in graph[u] if i != v][0]
vnext = [i for i in graph[v] if i != u][0]
grid_sides = [[u, unext], [v, vnext]]
u, v = unext, vnext
while True:
unext = [i for i in graph[u] if i != grid_sides[0][-2] and i != v]
vnext = [i for i in graph[v] if i != grid_sides[1][-2] and i != u]
if len(unext) == 0:
break
grid_sides[0].append(unext[0])
grid_sides[1].append(vnext[0])
u, v = unext[0], vnext[0]
else:
grid_sides = []
u0 = list(corners)[0]
for u in graph[u0]:
side = [u0, u]
v = [i for i in graph[u] if i in sides and i != side[-2]]
while v:
u = v[0]
side.append(u)
v = [i for i in graph[u] if i in sides and i != side[-2]]
u = [i for i in graph[u] if i in corners and i != side[-2]][0]
side.append(u)
grid_sides.append(side)
v = [i for i in graph[u] if i != side[-2]]
if v:
v = v[0]
side = [u, v]
u = v
v = [i for i in graph[u] if i in sides and i != side[-2]]
while v:
u = v[0]
side.append(u)
v = [i for i in graph[u] if i in sides and i != side[-2]]
u = [i for i in graph[u] if i in corners and i != side[-2]][0]
side.append(u)
grid_sides.append(side)
return grid_sides
def merge_grid(graph, grid_sides, inner_grid):
lu, ld, ru, rd = inner_grid[0][0], inner_grid[-1][0], inner_grid[0][-1], inner_grid[-1][-1]
for side in grid_sides:
if lu in graph[side[1]] and ru in graph[side[-2]]:
up = side
break
if lu in graph[side[-2]] and ru in graph[side[1]]:
up = side[::-1]
break
for side in grid_sides:
if side[0] == up[0] and side[-1] != up[-1]:
left = side
break
if side[-1] == up[0] and side[0] != up[-1]:
left = side[::-1]
break
for side in grid_sides:
if side[0] == up[-1] and side[-1] != up[0]:
right = side
break
if side[-1] == up[-1] and side[0] != up[0]:
right = side[::-1]
break
for side in grid_sides:
if side[0] == left[-1] and side[-1] == right[-1]:
down = side
break
if side[-1] == left[-1] and side[0] == right[-1]:
down = side[::-1]
break
grid = [up] + [[l] + side + [r] for l, side, r in zip(left[1:-1], inner_grid, right[1:-1])] + [down]
return grid
def construct(points, edges):
if len(points) <= 1:
return [list(points)]
graph, corners, sides, inners = classify_points(points, edges)
grid_sides = construct_grid_sides(graph, corners, sides)
if len(inners) == 0:
return grid_sides
inner_edges = [[u, v] for u, v in edges if u in inners and v in inners]
inner_grid = construct(inners, inner_edges)
grid = merge_grid(graph, grid_sides, inner_grid)
return grid
points = [i for i in range(n)]
return construct(points, edges)
提交代码评测得到:耗时5791ms,占用内存712.5MB。