给定一个2D数组,其中单元格被标记并组合在一起形成不同的线性形状,您将如何识别重复的形状。
0010000100000000000000000000
0010000100000000000000000000
0011100100000100000000011100
0000000100000111111000000000
0010000111100100000000000000
0110000000000001111000000000
0010000100000000000000000111
0000000001000000000011110000
0000000001111110000000000000
0010000001000000000000000000
这里我们有3个重复的形状:
1
111111个
1
111
1
到目前为止我所想的是:
为了存储形状,我将为每个形状制作树,节点结构将是
typedef struct node{
struct node * leftchild;
struct node * rightchild;
struct node * downchild;
};
在第2步中,我还将根元素存储在数组中。
现在我有每个形状的根元素。我将不得不比较数组中存在的根节点所代表的每一棵树,以找出任何重复的形状。
此解决方案有效吗?此外,我觉得复杂性将是巨大的。
答案 0 :(得分:2)
是的,这将有效。现在的问题是比较你获得的树木。
例如,您可以通过一串字母L,D,R,B
(B表示后面)来表示树的任何左遍。您的示例中的树将具有'DDBRRRRRBBBBBB'
,'RRBB'
和''
(空)编码。显然,相同的树具有相同的编码,反之亦然。
现在,对于每棵树,我们都有一些字符串表示。我们可以更进一步,并计算该字符串的哈希值。让我们说我们有H阵列的哈希。现在要找到重复项,我们可以对哈希值数组进行排序,所有相同的哈希值将组合在一起。
要恢复哪些原始形状(树)是相同的,只需要保留对树的引用以及散列,以便排序后的顺序洗牌不会出现问题。
<强>复杂性即可。我们假设网格大小为NxM
,它包含K
个形状。树构造部分是O(N*M)
(此处也是哈希,您可以在运行中计算哈希值)和排序O(K*logK)
。假设K=O(N*M)
会导致O(N*M)+O(N*M*log(N*M)) = O(N*M*log(N*M))
复杂性。一点都不大)
答案 1 :(得分:1)
也许你可以添加:对于每个识别的形状,存储1的数量。然后,当两个形状具有相同数量的1时,您只需要调用(可能是昂贵的)完全比较例程。 另外,第二个便宜的检查是每个形状的行数和列数。
答案 2 :(得分:0)
更简单的线性形状可以用数字表示。
1
111111
1
可以基于最左边和最右边的索引表示为111.161。最左边的索引位于小数的左侧,右侧的索引位于小数的右侧。
右移和下移是构建一个连通组件的有效移动。其他动作会生成一个列表。另一个例子
1111
1111111
111
可以分解为
1111
11 11111
1 11
这可以表示为111.452-> 12.11
与间隙相似的例子
111 111
1111
可以分解为
111 111
1111
这可以表示为13.36-> 1.3
由于数字代表图案中1s的宽度,我们只能在一次拍摄中处理宽度最大为9的矩形。
111111111111
可以表示为
111111111 111
1.9〜&GT; 1.3
因此,每个模式都表示为浮点数列表。由于您只扫描每个元素一次,因此需要花费O(N)时间。要查找重复项,您只需对元素进行排序即可。
假设有n个连通分量,其中每个分量表示为最大m的长度列表。所以整体O(nlogn * m)。