如何在O(n * log(n))时间内找到并打印n个给定圆的交点?

时间:2013-11-28 11:54:30

标签: algorithm math graphics computational-geometry

我正在寻找O(n*logn)算法来查找和打印n个给定圈子的交叉点。每个圆圈由其中心和半径指定。

O(n 2 )算法在于检查中心之间的距离是否小于或等于半径的总和(被比较的两个圆的总和)。但是,我正在寻找一个更快的!

类似的问题是线段的交叉。我认为即使我的问题也可以使用line sweep algorithm来解决,但我无法弄清楚如何修改事件队列以防万一。

请注意以下角落情况。黑点表示事件点(根据用户Sneftel的解决方案,在箭头标记的圆圈下方不会打印

Please take care of this in your solution

2 个答案:

答案 0 :(得分:3)

线扫描算法只会在遇到左极值(即(x-r, y))时将圆圈添加到列表中,并在遇到右极值时从列表中删除。在向列表中添加圆圈之前,请根据列表中已有的圆圈进行检查。因此,您的事件队列基本上是所有圆圈的左右极值,按x排序。 (请注意,您提前了解所有事件,因此在正常意义上它并非真正的“队列”。)

这也称为“扫除和修剪”。

答案 1 :(得分:2)

这是我根据用户Sneftel算法的修改找到的正确解决方案,该算法并非适用于所有情况。

enter image description here

图1:用有界框表示每个圆圈 现在使用扫描线方法,将扫描线平行移动到y轴,我们需要两个线段来表示每个圆的y范围,如图2所示。

enter image description here

完成后,问题将减少到以下几点:

enter image description here

这里有2个线段代表一个圆圈 扫描线状态可以保持为任何平衡的动态数据结构,如AVL树,跳过列表,红黑树,其插入/更新/删除/检索时间最多为O(logn)。 在这种情况下的比较函数将检查对应于相邻线段的两个圆是否相交(代替检查线段如在原始线扫描方法中相交以找出线段交叉点)。这可以在O(1)时间内完成,因为需要恒定的操作量 事件点数:4n(对于n个圆= = 2n个线段=> 4n个端点)
复杂度= O(4nlog(4n))= O(nlogn)