找到矩阵中具有某些属性的所有矩形区域

时间:2012-06-12 18:00:44

标签: algorithm complexity-theory rectangles

给出一个n * m矩阵,其可能的值为1,2和null:

  . . . . . 1 . .
  . 1 . . . . . 1
  . . . 2 . . . .
  . . . . 2 . . .
  1 . . . . . 1 .
  . . . . . . . .
  . . 1 . . 2 . .
  2 . . . . . . 1

我正在寻找所有块B(包含(x0,y0)和(x1,y1)之间的所有值):

  • 至少包含一个'1'
  • 不包含'2'
  • 不是具有上述属性的另一个块的子集

示例:

blocks

红色,绿色和蓝色区域都包含'1',没有'2',并且不是更大区域的一部分。 当然,在这张图片中有超过3个这样的块。我想找到所有这些块。

找到所有这些区域的快速方法是什么?

我有一个工作强力解决方案,迭代所有可能的矩形,检查它们是否符合前两个标准;然后迭代所有找到的矩形,删除另一个矩形中包含的所有矩形;我可以通过先删除连续相同的行和列来加快速度。但我相当确定有更快的方法。

3 个答案:

答案 0 :(得分:1)

你可以在考虑每个矩形和一个适当聪明的解决方案之间找到它。

例如,从每个1开始,您可以创建一个矩形,并逐渐向四个方向向外扩展其边缘。当你点击2时停止,如果(a)你必须在所有4个方向停止,并且(b)你之前没有看过这个矩形,则记录这个矩形。

然后回溯:你需要能够从左上角附近的1开始生成红色矩形和绿色矩形。

但是,这个算法有一些非常糟糕的最坏情况。我想到了一个由所有1组成的输入。所以它确实需要与其他一些聪明或输入的约束相结合。

答案 1 :(得分:1)

考虑更简单的一维问题:

查找.2.1.1...12....2..1.1..2.1..2的所有子字符串,其中包含至少一个1且不包含2,并且不是此字符串的子字符串。这可以在线性时间内解决,您只需要检查两个1之间是否有2

现在,您可以轻松地将此算法应用于二维问题:

1≤i≤j≤n使用以下法律对ij的所有行进行求和:.+.=..+1=1.+2=2,{{1} }},1+1=11+2=2并将一维算法应用于结果行。

复杂性:O(n²m)。

答案 2 :(得分:1)

我终于找到了几乎在线性时间内工作的解决方案(取决于找到的区域数量,这个因素很小)。我认为这是最快的解决方案。

受到这个答案的启发:https://stackoverflow.com/a/7353193/145999(图片也从那里拍摄)

首先,我按列选择矩阵,创建一个新矩阵M1,测量到最后一个'1'的步数,矩阵M2测量到最后'2'的步数 M1 & M2

想象上图中任何灰色块中的“1”或“2”

最后我有M1和M2看起来像这样:

enter image description here

没有通过行反转M1和M2:

enter image description here

我执行以下算法:

 foundAreas = new list()

 For each row y backwards:
     potentialAreas = new List()
     for each column x:
        if M2[x,y]>M2[x-1,y]:
            add to potentialAreas: 
                new Area(left=x,height=M2[x,y],hasOne=M1[x,y],hasTop=false)
        if M2[x,y]<M2[x-1,y]:
            for each area in potentialAreas:
                 if area.hasTop and area.hasOne<area.height:
                        add to foundAreas:
                             new Box(Area.left,y-area.height,x,y)
            if M2[x,y]==0: delete all potentialAreas
            else:
                 find the area in potentialAreas with height=M2[x,y] 
                 or the one with the closest bigger height: set its height to M2[x,y]
                 delete all potentialAreas with a bigger height

            for each area in potentialAreas:
                 if area.hasOne>M1[x,y]: area.hasOne=M1[x,y]
                 if M2[x,y+1]==0: area.hasTop=true

now foundAreas包含具有所需属性的所有矩形。