对点间隔执行二进制搜索

时间:2013-11-26 19:09:12

标签: java search binary overflow

我要解释我的问题,试图尽可能清楚。 Point[] right是一个有序的点数组,每个Point对象只有一对Long x, y

现在,这是我的目标。如果Point p具有p.y坐标,我必须找到几个点Point p1, p2,其中包含(根据y坐标)p,显然使用二分搜索。这是我的迭代实现。

        /* Binary search for leftmost edge intersected by p */
        Point p1, p2;
        long px = p.x, py = p.y;
        long div = 2;
        long index = (left.length-1)/div;
        while(true) {
//          System.out.println("Left search-index:"+index+" Div: "+div);
            if(left[(int) index].y.compareTo(p.y) >= 0){
                if(left[(int) (index+1)].y.compareTo(p.y) <= 0){    
                    p1 = left[(int) index];
                    p2 = left[(int) (index + 1)];
//                  System.out.println("p1 "+p1.x+" "+p1.y+"; p2 "+p2.x+" "+p2.y);
                    break;
                }
                else {
                    if(index/div == 0)
                        index = index + 1;
                    else
                        index = index + index/div;
                }
            }
            else {
                if(index/div == 0)
                    index = index - 1;
                else index = index - index/div;
            }
            div = 2*div;
        }

现在,问题:

  1. 这实际上是二元搜索吗?
  2. div可能会遭遇溢出吗?我知道在运行时它抛出一个异常,但我不知道是什么以及由谁。 (此问题在SPOJ提交时发生,我所拥有的唯一信息是NZEC Runtime Error)。
  3. 有提高性能的方法吗?我期待一个5000-10000点的阵列。
  4. 我尝试使用75+条目数组,并且有执行的痕迹。 (请注意,此搜索是在两个不同的数组leftright上执行的,每个数组包含大约75/2个元素。

    Left search-index:20 Div: 2
    Left search-index:10 Div: 4
    Left search-index:12 Div: 8
    Left search-index:13 Div: 16
    Left search-index:14 Div: 32
    Left search-index:15 Div: 64
    Left search-index:16 Div: 128
    Left search-index:17 Div: 256
    Left search-index:18 Div: 512
    Right search-index:17 Div: 2
    Right search-index:9 Div: 4
    Right search-index:11 Div: 8
    Right search-index:12 Div: 16
    Right search-index:13 Div: 32
    Right search-index:14 Div: 64
    Right search-index:15 Div: 128
    Right search-index:16 Div: 256
    true
    Left search-index:20 Div: 2
    Left search-index:10 Div: 4
    Left search-index:12 Div: 8
    Left search-index:13 Div: 16
    Left search-index:14 Div: 32
    Left search-index:15 Div: 64
    Left search-index:16 Div: 128
    Left search-index:17 Div: 256
    false
    Left search-index:20 Div: 2
    Left search-index:30 Div: 4
    Left search-index:23 Div: 8
    Left search-index:25 Div: 16
    Right search-index:17 Div: 2
    Right search-index:9 Div: 4
    Right search-index:11 Div: 8
    Right search-index:12 Div: 16
    false
    

3 个答案:

答案 0 :(得分:1)

此实现具有二进制搜索的概念。二进制搜索保持两个边框:左边和右边,你只有一个。所以这可能导致一些无限循环,当它回落到一条线上时:

else index = index - index/div;

即。 index是100,你已经检查了90,所以答案在90到100之间,但是它会回落到50并且可能无限循环,就像它已经在这个区域一样。

编程中的许多错误并不容易找到:Nearly All Binary Searches and Mergesorts are Broken

所以你可以使用标准方法(注意pos可以是否定的):

int pos = Arrays.binarySearch(p);

它会为您提供所需的排名,答案是成对(A[pos - 1], A[pos])(A[pos], A[pos + 1])

线性搜索也可以在这里工作,因为只有10.000个元素。

JavaDoc

> Returns: 
> index of the search key, if it is contained in the array;
> otherwise, (-(insertion point) - 1). The insertion point is defined as
> the point at which the key would be inserted into the array: the index
> of the first element greater than the key, or a.length if all elements
> in the array are less than the specified key. Note that this
> guarantees that the return value will be >= 0 if and only if the key
> is found.

答案 1 :(得分:1)

我用严格的二进制搜索编写了一个新版本。你怎么看?它不断返回正确的值,但不适用于SPOJ。

    low = 0; high = right.length - 1;
    mid = 0;

    while(low <= high) {
        mid = (low + high) >>> 1;
        System.out.println("MID: "+mid);
        c1 = right[mid].y;
        c2 = right[mid+1].y;

        if(py >= c1 && py <= c2) {
            p3 = right[mid];
            p4 = right[mid +1];
            break;
        }

        else if(py < c1)
            high = mid - 1;

        else
            low = mid + 1;
    }

答案 2 :(得分:0)

index/div==0唯一的方法是当索引为0时,因此index=index-1将导致-1值,这是非法索引或索引小于div大时间。
在Java中,数组的索引和长度是int而不是long