我已经提出了这个解决方案来在排序数组中严格实现下限:
long lowerBound(long key, long size, long *a){
long low = 0, high = size, mid;
if(a[low] >= key){
return -1;
}
while(low < high){
mid = (low+high)/2;
if(a[mid] >= key){
high = mid - 1;
} else{
low = mid;
}
}
return low;
}
但这似乎不起作用。它在一些测试用例中失败了。例如:
A [7] = {0,1,1,3,5,5,10}
key = 4
进入无限循环。
以下是测试运行:
第一次迭代后: low = 3,high = 7,mid = 3
第二次迭代后: low = 3,high = 4,mid = 5
第三次迭代后: 低= 3,高= 4,中= 3。 然后它就卡住了。
任何人都可以指出我正确的方向。在此先感谢!!
答案 0 :(得分:2)
它会被卡住&#34;因为当您的low
等于high - 1
时,mid
变为low
:(low+low+1)/2 == low
,则a[mid] >= key
为false
且mid
}再次设置为low
。如果low
,您需要将mid + 1
设置为a[mid] < key
,否则将high
设置为mid
。然后你会发现第一次出现key,或者,如果没有元素,等于key,第一次出现的元素大于key,如果所有元素都小于key,你会得到高的初始值。
UPD:而且,由于它的二进制搜索,您始终获取low == high - 1
。下次记住这一点!
UPD2:还有一件事!最好使用mid = low+((high-low)/2)
,因为这样可以防止出现一些溢出错误。
答案 1 :(得分:0)
举个例子:
low = 3
high = 4
那么你的代码会做什么?
while(low < high){ // True as 3 is less than 4
mid = (low+high)/2; // (3+4)/2 --> mid = 3
if(a[mid] >= key){ // a[3] is 3. And 3 isn't greater or equal 4 so this is false
high = mid - 1;
} else{ // So you take the else part
low = mid; // low is assigned 3. So you are back
// where you started and have an endless loop
}
您需要确保low
和high
的分配不只是分配他们已有的值。
例如:
else {
if (low == mid) return low;
low = mid;
}
答案 2 :(得分:0)
如果数组的每个元素都是唯一的,您可以使用以下内容:
long binsearch(long *a, long size, long key) {
long lo = 0;
long hi = size-1;
if (hi == -1)
return -1;
while (1) {
long mid = ( lo + hi ) / 2;
if (a[mid] == key)
return mid;
if (a[mid] < key) {
hi = mid - 1;
if (lo > hi)
return ~mid;
} else {
lo = mid + 1;
if (lo > hi)
return ~lo;
}
}
}
但你的阵列可能有重复,你想找到第一个,所以我们需要调整被认为匹配的东西。
long binsearch_first(long *a, long size, long key) {
long lo = 0;
long hi = size-1;
if (hi == -1)
return -1;
while (1) {
long mid = ( lo + hi ) / 2;
if (a[mid] == key && ( mid == 0 || a[mid-1] != key ))
return mid;
if (a[mid] <= key) {
hi = mid - 1;
if (lo > hi)
return ~mid;
} else {
lo = mid + 1;
if (lo > hi)
return ~lo;
}
}
}
您可能已经注意到了特殊的回报值。如果不是key
,它的优势在于返回key
。这会告诉您如果要将其添加到数组中,请插入long i = binsearch_first(a, a_size, key);
if (i >= 0) {
printf("The first %ld was found at index %ld.\n", $key, i);
} else {
printf("%ld wasn't found. It would have been found at index %ld.", $key, ~i);
}
的位置。
FileName1
FileName2
FileName5
FileName6
答案 3 :(得分:-1)
你从high = size
开始,所以上限超出了范围,应该保持这种状态,也就是说,它永远不是解决方案。
因此会出现两个错误:结束条件以及新high
值的设置。
结束条件应为
while (high - low > 1)
之后解决方案将为low
。并且新high
值的设置应为
if(a[mid] > key){ // change from >=
high = mid; // mid is not valid
}