我试图弄清楚如何设计一个能够以O((n + s)log n)复杂度完成此任务的算法.是交叉点的数量.我试过在网上搜索,却找不到东西.
无论如何,我意识到拥有一个好的数据结构是关键.我在java:TreeMap中使用Red Black Tree实现.我还使用着名的(?)扫描线算法来帮助我处理我的问题.
让我先解释一下我的设置.
我有一个调度程序.这是一个PriorityQueue,我的圈子根据最左边的坐标排序(升序).scheduler.next()基本上轮询PriorityQueue,返回下一个最左边的圆圈.
public Circle next()
{ return this.pq.poll(); }
Run Code Online (Sandbox Code Playgroud)
我这里还有一个包含4n个事件点的数组.授予每个圆圈有2个事件点:大多数左x和最右x.调度程序有一个方法sweepline()来获取下一个事件点.
public Double sweepline()
{ return this.schedule[pointer++]; }
Run Code Online (Sandbox Code Playgroud)
我也有状态.扫描线状态更精确.根据该理论,状态包含有资格相互比较的圆圈.在整个故事中拥有扫描线的关键在于你能够排除很多候选人,因为他们根本不在当前圈子的半径范围内.
我用一个实现了状态TreeMap<Double, Circle>.双重是circle.getMostLeftCoord().
此TreeMap保证O(log n)用于插入/删除/查找.
算法本身的实现方式如下:
Double sweepLine = scheduler.sweepline();
Circle c = null;
while (notDone){
while((!scheduler.isEmpty()) && (c = scheduler.next()).getMostLeftCoord() >= sweepLine)
status.add(c);
/*
* Delete the oldest circles that the sweepline has left behind
*/
while(status.oldestCircle().getMostRightCoord() < sweepLine)
status.deleteOldest();
Circle otherCircle;
for(Map.Entry<Double, Circle> entry: status.keys()){
otherCircle = entry.getValue();
if(!c.equals(otherCircle)){ …Run Code Online (Sandbox Code Playgroud)