给定2D阵列中的标记单元格,找到由这些标记单元格形成的重复形状

时间:2013-07-18 14:17:14

标签: c algorithm data-structures multidimensional-array shapes

给定一个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;  
    };  
  1. 我将逐个细胞遍历矩阵,同时保持一个visited [] []数组。
  2. 当我找到一个未被访问的'1'时,我将为该单元格创建一个新节点,并将该节点标记为该形状的根节点,因为这将是该形状的第一个访问节点。
  3. 然后我将检查在步骤2中找到的根细胞的立即左,右和下细胞,并且(如果1)将它们添加到相应的根'子节点。然后用这些左右单元格重复它以完成该形状的树。
  4. 在第2步中,我还将根元素存储在数组中。

    现在我有每个形状的根元素。我将不得不比较数组中存在的根节点所代表的每一棵树,以找出任何重复的形状。

    此解决方案有效吗?此外,我觉得复杂性将是巨大的。

3 个答案:

答案 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)。