计算端点位于圆上的线段的交点数量?

时间:2017-03-25 14:22:09

标签: java algorithm

  

输入是一个2n个整数的数组,它通过说明圆上的点如何配对来定义线段   和连接。 (每个点都有自己的连接对。)

     

数组[2,3,0,1]读取:

     

点0连接到点2
点1连接到点3   
点2连接到点0
点3连接到   第1点

     

意思是我们有线段(0,2)和(1,3)。

     

这些点位于圆圈上,顺序与它们相同   位于阵列中。 (他们的确切坐标是无关紧要的。)

     

这是我的数组示例的图片。 (发生了1次交叉。)

     

enter image description here

     

输出是交叉点的数量。 (2个线段接触的点数。)

     

计算这个的最佳(最快)方法是什么?

我尝试了什么:

public static int count(int[] world) {
    int i = 0;
    int intersections = 0;
    int endpoint = 0;

    // run trought all points in order, find their pairs and check if the line they make is intersected
    while (i < world.length - 1) {

        if (world[i] == i+1) { // if 2 neighbouring points are connected, there are no intersections with the line they make
            i++;
        } else if (world[i] > i) { // don't need to check previously checked pairs
            endpoint = world[i];

                // check if any intersections with the line L(i,world[i]):
                // This goes through all points that are located before the endpoint of the line defined by point i and its pair world[i]
                // And checks if their pair is located after the endpoint, which means that the line they make intersects the line L(i,world[i])
                for (int j = i+1; j < endpoint; j++) {
                    if (world[j] > endpoint) {
                        intersections++;
                    }
            }
        } 
        i++;
    }

    return intersections;
}

感谢saby的回答,我也对此进行了编码:

    public static int countIntersections(int[] world) {
    int intersections = 0;

    for (int i = 1; i < world.length; i++) {
        for (int j = 0; j < i; j++) {
            if (!C(i,world[i],i-j,world[i-j])) {
                intersections++;
            }
        }
    }

    return intersections;
}

public static boolean C(int a, int b, int x, int y) {
    return ((a <= x && b <= x) || (a >= x && b <= y) || (a >= x && b >= x));
}

与我的初始代码相同的结果意味着它们都有效!但我的初始代码比这个快。

我会接受他的答案,因为两个代码都有效,优化问题更适合Codereview

1 个答案:

答案 0 :(得分:0)

观察:鉴于两个细分L1: [a, b]L2: [x, y],他们 DONT 相交,当且仅当(a < x && b > y) || (x < a && y > b)。 请调用此条件C(L1, l2)

算法概要

  • 逐个遍历线段
  • 采取第一线段L1
  • 获取细分线段L2并计算条件C(L1, L2)。如果是假,则将交叉点数加1。
  • 获取L3段并计算C(L3, L1)C(L3, L2)。相应地添加1。
  • 对于段Ln,您必须计算C(Ln, Ln-1)C(Ln, Ln-2) ...
  • 时间复杂度:O(n^2)n是段数