我有一组m个非旋转,整数(像素)对齐的矩形,每个矩形可能重叠也可能不重叠。矩形覆盖数千个像素。我需要找到覆盖m个矩形中n个所覆盖的所有区域的最小大小的边界框。
这样做(脏)的方法是绘制一个覆盖所有目标区域的画布。这是O(mk),其中m是矩形的数量,k是每个矩形的像素数。然而,由于k远大于m,我认为有更好的解决方案。
这感觉就像一个动态的编程问题......但是我无法弄清楚递归。
解决方案哪个更好但仍然不是很好:
对X方向上的所有矩形的起点和终点O(mlogm)进行排序,迭代并找到可能有超过n个矩形的x位置,O(m)循环。对于可能有n个以上矩形的每个x位置,取该位置的矩形并对该位置的起点和终点进行排序(O(mlogm))。找到重叠区域,跟踪那条路的边界。总的来说,O(m ^ 2logm)。
答案 0 :(得分:1)
Hello MadScienceDreams,
为了澄清,边界框也是非旋转的,对吗?
如果是这种情况,那么只需跟踪四个变量:minX, maxX, minY, maxY
- 表示定义边界框的最左侧,最右侧,最顶部和最底部像素,循环通过每个矩形更新四个变量,并在给定这四个变量的情况下定义新的边界框。
修改强>
看起来你问的是找到某些矩形子集的边界,而不是整个集合。
所以你有M个矩形,然后从中选择N个矩形,找到其中的边界。
即使在这种情况下,循环N个矩形并跟踪它们的界限最多也是O(m),这一点都不差。
我觉得我必须误解你的问题,因为这个回答不是你可能想要的;你的问题实际上是试图询问如何预先计算边界,以便给定任何子集,知道恒定时间内的总界限?
答案 1 :(得分:0)
这是否定义了您的问题?对于边界框 => #rect_label >= n
答案 2 :(得分:0)
我们如何从一个盒子开始,找到距离它最近的最近一个角落的下一个盒子。现在我们有一个有两个盒子的区域。递归地找到下一个区域,直到我们有n个框。
虽然我们需要从每个盒子开始,但我们只需要积极地处理当前最小的区域。效果是我们从最小的盒子集群开始,然后从那里扩展出来。
如果n更接近m而不是0,我们可以反转搜索树,以便从全方位封闭框开始,切断每个边框以创建下一个搜索级别。假设我们只是积极地处理剩余的最小区域,那么我们首先要切断最空的区域。
太复杂了吗?对不起,我记不住这次搜索的名字了。我不擅长数学,所以我会跳过O符号。 > _<
答案 3 :(得分:0)
我提出以下算法:
prepareData();
if (findBorder('left')) {
foreach (direction in ['top', 'right', 'bottom']) {
findBorder(direction)
}
} else noIntersectionExists
prepareData(O(mlogm)):
订购垂直边界和水平边界
将结果保存为:
- 两个指向矩形的数组(arrX和arrY)
- 将索引保存为矩形的属性(rectangle.leftIndex,rectangle.topIndex等
findBorder(左)://其他方向相似 最佳情况O(n),最坏情况O(2m-n)
arrIntersections = new Array;
//an intersection has a depth (number of rectangles intersected), a top and bottom border and list of rectangles
for(i=0; i < 2*m-n-1; i++){ // or (i = 2*m-1; i > n; i--)
if(isLeftBorder(arrX[i])){
addToIntersections(arrX[i].rectangle, direction);
if(max(intersections.depth) = n) break;
} else {
removeFromIntersections(arrX[i].rectangle, direction);
}
}
addToIntersections(矩形,方向)://对direction = left的解释 最佳情况:O(n),最坏情况:O(m)
hasIntersected = false;
foreach(intersection in intersection){
if(intersect(intersection, rectangle)){
hasIntersected = true
intersections[] = {
depth: intersection.depth,
bottom: min(intersection.bottom, rectangle.bottom),
top: max(...)}
intersection.depth++
intersection.bottom = max(intersection.bottom, rectangle.bottom)
intersection.top = max(...)
}
}
if(!hasIntersected)
intersections[]={depth:1, bottom:rectangle.bottom, top:rectangle.top}
这给出了O(n ^ 2)和O(m *(m-n / 2))之间的整体顺序
我希望我的伪代码足够清晰