二进制搜索算法实现

Binary Search algorithm implementations

我遇到过多个问题,这些问题使用 二分搜索 的变体来得出最终答案。这些问题包括找到数字平方根的下限、检查数字是否是完全平方数、在旋转数组中找到最小值、在数组中找到数字的第一个索引等。

所有算法都包含经过适当修改的低、高和中变量。

我在网上阅读了这些算法的几种变体,这些算法总是很可能出现一个错误,导致它错过极端情况。对于以下变体,是否有任何标准可以帮助我理解何时应该使用哪个?

1.变量初始化

选项 1:低 = 0,高 = arr.length

选项 2:低 = 0,高 = arr.length - 1

选项 1:低 = 1,高 = arr.length

2。循环条件

选项 1:同时(低 < 高)

选项 2:同时(低 <= 高)

3。中变量计算

选项 1:中 = (低 + 高) / 2;

选项2:中=低+(高-低)/ 2;

4。条件检查和更新到低和高

选项 1:低 = 中 AND 高 = 中

选项 2:低 = 中 AND 高 = 中 - 1

选项 3:低 = 中 + 1 AND 高 = 中

选项 4:低 = 中 + 1 AND 高 = 中 - 1

编辑:采用的假设是 3 态输出。数组索引从 0 开始。

您提到的选项并没有更好和更差。通常它只取决于一个实现,例如如果你通过 high=arr.length 那么你宁愿写 while(low < high) 而不是 while(low <= high).

事实上,其中一些 差异可能有意义 。如果我们考虑使用二进制搜索算法在数组 A 中找到你的 X 数,并且会有一些(不仅仅是一个)元素等于 X,你可以找到第一个或最后一个的索引 - 这取决于实现。

好吧,您可以通过多种方式使其发挥作用,但是:

1) 我用low=0, high=arr.length。如果我要调用变量 lowhigh,那么我希望始终使用 low<=high,即使在搜索结束时也是如此。 arr.length==0

时这样也比较容易想到

2) while (low<high)。这对应于 (1) 的答案。当循环完成后,我喜欢low==high,所以我不必担心使用哪个

3) 始终使用 mid=low+(high-low)/2mid = low+((high-low)>>1)。当数组太长并给出负面结果时,另一个选项会溢出。

4) 这取决于您使用的比较类型(三态与二态输出),以及其他答案。对于 2 态比较和上述答案,您会得到 low=mid+1high=mid。这是理想的,因为很明显每次迭代范围都会变小——mid+1 > low 显然,而 mid < high,因为 low<high(这是循环条件)和 (high-low)/2 向下舍入.