我正试图解决着名的天际线问题(见gif):
输入
(1,11,5),(2,6,7),(3,13,9),(12,7,16),(14,3,25),(19,18,22) ,(23,13,29),(24,4,28)
应该返回,其他建筑物后面的点应该消失,Y轴的变化坐标应该在返回的天际线中:
(1,11),(3,13),(9,0),(12,7),(16,3),(19,18),(22,3),(23,13) ,(29,0)
我试图通过对算法使用分而治之的方法来实现,以实现O(n lg n)的运行时间,但是我被困在合并部分。
每当我想到它,我都会感到困惑。例如,我检查天际线是哪一个,例如它具有较低的x坐标,然后我将它的高度添加到我的新天际线。但后来我遇到了另外两个天际线后面的天际线,我怎么才能发现这个“碰撞”?
首先通过检查left.x2<来检查天际是否有任何重叠。 right.x1?但是我想我应该先检查一下?在x轴上重叠优先级,一切都变成了一个鸡蛋大的混乱。
也许我觉得太复杂了?我需要的是每个交叉点的最高y坐标集,我应该像这样接近吗?
答案 0 :(得分:7)
我认为这应该是一种更容易解决问题的方法:
将x坐标拆分为每个矩形的开始和结束对象,如下所示:
rect(x1, y, x2) -> (x1, y, "start", reference to rect),
(x2, y, "finish", reference to rect)
类似于:
class MyStruct
{
Rectangle rect;
int x, y;
bool isStart;
}
O(n log n)
)O(n)
)
O(log n)
)O(1)
)O(log n)
)(current.finishX, new.y)
添加到输出(O(1)
)(如果集合为空,则添加(current.finishX, 0)
到而不是输出)所以O(n log n)
。
答案 1 :(得分:0)
这可以通过修改合并排序算法来实现。天际线的算法如下:
<强> ConstructSkyLine 强>
ConstructSkyLine(List B ) --------------- O(nlogn)
{
If(B.size() == 1)
{
List skyLineList = new List();
SKYLINE = new SKYLINE(B.XL, B.XR, B.H);
skyLineList.add(SKYLINE);
Return skyLineList;
}
B1, B2 <-- Split(B);
List S1 <-- ConstructSkyLine(B1);
List S2 <-- ConstructSkyLine(B2);
List S <-- MergeSkyline(S1, S2);
Return S;
}
<强> MergeSkyline 强>
MergeSkyline(List S1, List S2) --------------- O(n)
{
List< SKYLINEENTRY> skylineEntryList = new ArrayList<SKYLINEENTRY>();
while (S1.isEmpty() && S2.isEmpty())--------------- O(n)
{
S1Item <-- S1.get(0);
S2Item <-- S2.get(0);
If (S1Item.XL < S2Item.XL)
{
Merge(S1, S2, skylineEntryList); --------------- O(n)
}
Else
{
Merge(S2, S1, skylineEntryList); --------------- O(n)
}
}
If(!S1.isEmpty())
{
skylineEntryList.add(S1);
}
If(!S2.isEmpty())
{
skylineEntryList.add(S2);
}
Retrun skylineEntryList;
}
合并
Merge(S1, S2, skylineEntryList) --------------- O(n)
{
SKYLINEENTRY <-- null;
S1Item <-- S1.get(0);
S2Item <-- S2.get(0);
SKYLINEENTRY.XL = S1Item.XL;
If(S1Item.XR > S2Item.XL) // means over lap
{
If(S1Item.H > S2Item.H) // S1 is higher.
{
SKYLINEENTRY.XR = S1Item.XR;
SKYLINEENTRY.H = S1Item.H;
S1.remove(S1Item); --------------- O(n)
skylineEntryList.add(SKYLINEENTRY);
if(S2Item.XR < S1Item.XR) // full overlap
{
S2.remove(S2Item); --------------- O(n)
}
Else // partial overlap
{
S2Item.XL <-- S1Item.XR;
}
}
Else //S2 is higher
{
SKYLINEENTRY.XR = S2Item.XL;
SKYLINEENTRY.H = S1Item.H;
if(S2Item.XR < S1Item.XR) // full overlap with S2
{
S1Item.XL = S2Item.XR;
}
Else // partial overlap
{
S1.remove(S1Item); --------------- O(n)
}
skylineEntryList.add(SKYLINEENTRY);
}
}
Else // no overlap
{
SKYLINEENTRY.XR = S1Item.XR;
SKYLINEENTRY.H = S1Item.H;
S1.remove(S1Item); --------------- O(n)
skylineEntryList.add(SKYLINEENTRY);
}
}