1 回答
TA贡献1829条经验 获得超7个赞
这是一个有效的修改算法。
public static int binarySearch(int[] arr, int v) {
int lo = -1;
int hi = arr.length - 1;
while (hi - lo > 1 ) {
int middle = (lo + hi) / 2;
if (arr[middle] > v) {
lo = middle;
} else {
hi = middle;
}
}
if (v == arr[hi]) {
return hi;
} else {
return -1;
}
}
关键点是:
区间 (lo, hi] 不包括左侧,包括右侧。
在每一步,我们都会丢弃一半的间隔。当我们下降到一个元素时,我们就会停下来。提前终止的尝试只能提供最小的性能提升,而它们通常会影响代码的易读性和/或引入错误。
当
arr[middle] = v
我们分配hi = middle
时,因此丢弃了右半部分。这是安全的,因为我们不关心v
过去的任何事件middle
。我们确实关心arr[middle]
,它可能是第一次出现也可能不是第一次出现,正是出于这个原因,我们将 (lo, hi] 包含在右边。如果出现v
beforemiddle
,我们将在后续迭代中找到它们。作为旁注,更自然的定义
[0, n)
包含在左侧,排除在右侧,可用于查找v
.
以我的经验,这种包容-排斥的区间定义产生了最短、最清晰和最通用的代码。人们一直在努力改进它,但他们经常陷入困境。
添加回答
举报