嘿,我正在使用二进制搜索方法在数组中查找数字,并且在查找中间数字以外的数字时会收到StackOverflow错误。
这是我的代码:
public static <T extends Comparable< ? super T>>
int find(T [] a, T x, int low, int high){
if(low>high)
throw new IllegalArgumentException();
int tmp = (high-low)/2;
if(a[tmp].compareTo(x)==0)
return tmp;
else if(a[tmp].compareTo(x)>0)
find(a,x,tmp,high);
else if(a[tmp].compareTo(x)<0)
find(a,x,low,tmp);
return -1;
}
另外,如果我尝试在tmp下查找数字,则返回-1。 我觉得我错过了一些但却无法弄清楚是什么。 先谢谢!
答案 0 :(得分:2)
这是问题所在:
if(a[tmp].compareTo(x)>0)
find(a,x,tmp,high);
else if(a[tmp].compareTo(x)<0)
find(a,x,low,tmp);
您应该在第一种情况下使用tmp + 1
,在第二种情况下使用tmp - 1
。否则,如果你有(比方说)low = 0,high = 1,那么你可能会使用相同的参数结束永久调用; tmp
最终会为0,如果x
超过a[0]
,您只需再次致电find(a, x, 0, 1)
。
编辑:你也以错误的方式进行比较。如果a[tmp].compareTo(x)
小于a[tmp]
,x
将返回小于0的值 - 即您应该在数组中查看以后,而不是更早。
编辑:目前你的“退出-1”代码被破坏了 - 如果a[tmp].compareTo(x)
返回一个既不高于零也不低于零的非零值,你只会返回-1。我挑战你找到这样一个整数:)(如果compareTo不稳定,它也会这样做,但这是一个单独的问题...)
一个选项是检测是否high == low
- 此时,如果没有达到正确的值,则可以返回-1:
int comparison = a[tmp].compareTo(x); // Let's just compare once...
if (comparison == 0) {
return tmp;
}
// This was our last chance!
if (high == low) {
return -1;
}
// If a[tmp] was lower than x, look later in the array. If it was higher than
// x, look earlier in the array.
return comparison < 0 ? find(a, x, tmp + 1, high) : find(a, x, low, tmp - 1);
答案 1 :(得分:2)
你需要:
else if(a[tmp].compareTo(x)>0)
find(a,x,tmp - 1,high);
else if(a[tmp].compareTo(x)<0)
find(a,x,low,tmp + 1);
否则,当你有low = 0
和high = 1
时,你基本上会以递归方式调用具有相同参数的函数。问题是你真的不需要再次查看mid
处的元素,因为你已经知道它相对于你想要找到的值是大于还是小。
此外,如果IllegalArgumentException
小于-1
,则应返回high
,而不是low
。
答案 2 :(得分:1)
public static <T extends Comparable< ? super T>>
int find(T [] a, T x, int low, int high){
if(low>high)
throw new IllegalArgumentException();
int tmp = (high+low)/2;//replaced - with + for average
if(a[tmp].compareTo(x)==0)
return tmp;
else if(a[tmp].compareTo(x)>0)
return find(a,x,tmp,high); //return the found index
else if(a[tmp].compareTo(x)<0)
return find(a,x,low,tmp);
return -1;
}
如果tmp是高和低的平均值,则需要添加它们然后除以2
也会在递归调用中返回找到的值