我要解释我的问题,试图尽可能清楚。 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;
}
现在,问题:
div
可能会遭遇溢出吗?我知道在运行时它抛出一个异常,但我不知道是什么以及由谁。 (此问题在SPOJ提交时发生,我所拥有的唯一信息是NZEC Runtime Error
)。我尝试使用75+条目数组,并且有执行的痕迹。 (请注意,此搜索是在两个不同的数组left
和right
上执行的,每个数组包含大约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
答案 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个元素。
> 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