我终于找到了一个几乎在线性时间内起作用的解决方案(有一个小因素取决于找到的区域的数量)。我认为这是最快的解决方案。
受此答案的启发:https ://stackoverflow.com/a/7353193/145999 (图片也取自那里)
首先,我逐列处理矩阵,创建一个新矩阵 M1 测量到最后一个“1”的步数和一个矩阵 M2 测量到最后一个“2”的步数

想象上图中任何灰色块中的“1”或“2”
最后我的 M1 和 M2 看起来像这样:

不按行反向通过 M1 和 M2:

我执行以下算法:
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
现在 foundAreas 包含所有具有所需属性的矩形。