假设我有一个0' s和1的MxN矩阵。它可能稀疏也可能不稀疏。
我想要一个函数来有效地找到数组中的矩形,其中矩形是指:
一组4个元素,它们都是创建a的4个角的1个元素 矩形,使得矩形的边与其正交 阵列轴。换句话说,矩形是一组4个1的元素 坐标[行索引,列索引]如下:[r1,c1],[r1,c2], [r2,c2],[r2,c1]。
E.g。此设置有一个矩形:
0 0 0 1 0 1 0
0 0 0 0 0 0 0
0 1 0 0 0 0 0
1 0 0 1 0 1 0
0 0 0 0 0 0 0
0 0 0 1 0 0 1
对于给定的MxN数组,我想要一个Python函数F(A),它返回一个子数组的数组L,其中每个子数组是矩形一角的坐标对(并包含矩形的所有4个角) )。对于阵列的相同元素是多个矩形的角的情况,可以复制这些坐标。
到目前为止,我的想法是:
1)找到数组中每个直角三角形顶点的坐标
2)检查每个直角三角形顶点坐标,看它是否是矩形的一部分
步骤1)可以通过找到那些1的元素并且在列总和> = 2的列中,并且在行和>&2的行中来实现。
然后,步骤2)将遍历确定为直角三角形的顶点的每个坐标。对于给定的直角三角形坐标对,它将遍历该列,查看该列中1)的每个其他直角三角形坐标。对于列中任何一对2个直角三角形点,它将检查哪一行具有较小的行总和,以便知道哪一行将更快地迭代。然后它将迭代该行中的所有直角三角形列坐标,并查看另一行是否在该列中也有一个直角三角形点。如果是这样,那4个点形成一个矩形。我认为这会有效,但会有重复,总的来说这个程序似乎是合理的计算密集型。有哪些更好的方法可以检测0-1阵列中的矩形角?
答案 0 :(得分:0)
这是我的头顶,并在洛杉矶国际机场停留5小时。以下是我的算法:
第1步:搜索所有行至少两个
| 0 0 0 1 0 1 0
| 0 0 0 0 0 0 0
| 0 1 0 0 0 0 0
\|/ 1 0 0 1 0 1 0
0 0 0 0 0 0 0
0 0 0 1 0 0 1
输出:
-> 0 0 0 1 0 1 0
0 0 0 0 0 0 0
0 1 0 0 0 0 0
-> 1 0 0 1 0 1 0
0 0 0 0 0 0 0
-> 0 0 0 1 0 0 1
第2步:对于每一行一对,获取与其对应的列中的一个的索引,让我们说第一行行:
-> 0 0 0 1 0 1 0
您检查以下列中的内容:
| |
\|/ \|/
0 0 0 1 0 1 0
0 0 0 0 0 0 0
0 1 0 0 0 0 0
1 0 0 1 0 1 0
0 0 0 0 0 0 0
0 0 0 1 0 0 1
第3步:如果两个索引匹配;返回所有四个指数。这可以很容易地访问,因为您知道所有步骤中的行和索引。在我们的例子中,第3列,第5列的搜索将返回3,假设您从0开始索引。所以我们得到以下的指标:
0 0 0 ->1 0 ->1 0
0 0 0 0 0 0 0
0 1 0 0 0 0 0
1 0 0 ->1 0 ->1 0
0 0 0 0 0 0 0
0 0 0 1 0 0 1
第4步:对所有对重复
算法复杂度
我知道您需要搜索columns * rows * number of pairs
,但您始终可以使用哈希映射来优化搜索O(1)
。这将使复杂性与对的数量相关联。如有任何问题,请随时发表评论。
答案 1 :(得分:0)
这是一个类似于@PseudoAj解决方案的Python实现。它将在构造dict
时从顶部开始处理行,其中键是x坐标,值是各自y坐标的集合。
对于以下步骤的每一行:
left, right
进行迭代,其中left < right
dict
开始交叉dict
醇>
代码:
from collections import defaultdict
from itertools import combinations
arr = [
[0, 0, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 1]
]
# List corner coords
result = []
# Dict {x: set(y1, y2, ...)} of 1s in processed rows
d = defaultdict(set)
for y, row in enumerate(arr):
# Find indexes of 1 from current row
coords = [i for i, x in enumerate(row) if x]
# Move to next row if less than two points
if len(coords) < 2:
continue
# For every pair on this row find all pairs on previous rows
for left, right in combinations(coords, 2):
for top in d[left] & d[right]:
result.append(((top, left), (top, right), (y, left), (y, right)))
# Add coordinates on this row to processed rows
for x in coords:
d[x].add(y)
print(result)
输出:
[((0, 3), (0, 5), (3, 3), (3, 5))]