我正在尝试编写一个函数,该函数获取一组元组作为参数,并检查给定字符是否在NxN网格中形成连续形状。元组是构成网格的列表中字符的索引。如果在另一个字符的正下方、上方或侧面有一个字符,则形状是连续的。
continuous not continous not continous
xxxxx xxxxx ooxxx
xxoox xxoox xxxxx
xxxoo ooxxx xxoox
xxxoo oxxxx xxoox
xxxxo xoxxx xxxxx
==============================
def connected(characters):
result = True
for i in characters:
if (i[0]+1, i[1]) in characters or (i[0]-1, i[1]) in characters or (i[0], i[1]+1) in characters or (i[0], i[1]-1) in characters:
result = True
characters.discard(i)
else:
result = False
return result
return result
>>>connected({(1, 3), (2, 1), (2, 3), (0, 3), (1, 1)})
会形成这种形状,因此它不会是连续的,但我的代码认为它是。
xxxo
xoxo
xoxo
xxxx
这在大多数情况下都是有效的,但当给定的字符形成两个独立的连续形状时就不起作用了,就像我上面给出的第二个错误的例子一样。我试图通过在检查后删除每个元组来解决这个问题,但我得到了
Traceback (most recent call last):
File "C:/Users/User/PycharmProjects/untitled6/venv/1.py", line 47, in <module>
connected({(1, 2), (1, 3), (2, 2), (0, 3), (0, 4)})
File "C:/Users/User/PycharmProjects/untitled6/venv/1.py", line 15, in connected
for i in grid:
RuntimeError: Set changed size during iteration
错误。我能做些什么来解决这个问题?
有关错误的更多信息,请参阅https://stackoverflow.com/a/38423075.基本上,如果你想在循环中修改一个集,你必须迭代一个集的副本。
除此之外,你的算法还有一个缺陷。
如果不丢弃当前角色,则仅检查每个角色是否都有邻居。这将是好的:
xxxxx
xoxox
xoxox
xxxxx
但如果你放弃当前角色,你可能会有惊喜:
xxx xxx
xox <- cur x x <- discarded
xox xox <- has no neighbor!
xxx xxx
经典算法基于树遍历:从任意非开始遍历所有直接链接的节点。如果所有节点都可见,则图形已连接。
我在这里使用DFS,但如果你想,你可以使用BFS:
def connected(characters):
seen = set()
stack = [next(iter(characters))] if characters else []
while stack:
c = stack.pop()
seen.add(c)
for other_c in [(c[0]+1, c[1]), (c[0]-1, c[1]), (c[0], c[1]+1), (c[0], c[1]-1)]:
if other_c not in seen and other_c in characters:
stack.append(other_c)
return not (characters - seen)
print(connected({(1, 3), (2, 1), (2, 3), (0, 3), (1, 1)}))
# False
print(connected({(1, 3), (2, 1), (2, 3), (0, 3), (1, 1), (1, 2)}))
# True